绑定到多个接口时,防止Ninject多次调用Initialize

Ahe*_*Ahe 20 ninject

我们有一个具体的单件服务,它实现了Ninject.IInitializable2个接口.问题是服务Initialize-methdod被调用2次,只需要一次.我们使用的是.NET 3.5和Ninject 2.0.0.0.

Ninject中是否存在一种模式可以防止这种情况发生.两个接口都没有实现Ninject.IInitializable.服务类是:

public class ConcreteService : IService1, IService2, Ninject.IInitializable
{
    public void Initialize()
    {
        // This is called twice!
    }
}
Run Code Online (Sandbox Code Playgroud)

模块看起来像这样:

public class ServiceModule : NinjectModule
{
    public override void Load()
    {
        this.Singleton<Iservice1, Iservice2, ConcreteService>();
    }
}
Run Code Online (Sandbox Code Playgroud)

Singleton是一个定义如下的扩展方法:

    public static void Singleton<K, T>(this NinjectModule module) where T : K
    {
        module.Bind<K>().To<T>().InSingletonScope();
    }

    public static void Singleton<K, L, T>(this NinjectModule module) 
        where T : K, L
    {
        Singleton<K, T>(module);
        module.Bind<L>().ToMethod(n => n.Kernel.Get<T>());
    }
Run Code Online (Sandbox Code Playgroud)

当然我们可以将bool initialized-member添加到ConcreteService并仅在它为false时进行初始化,但它似乎有点像黑客.并且它需要在实现两个或更多接口的每个服务中重复相同的逻辑.


感谢所有的答案!我从所有人那里学到了一些东西!(我很难确定哪一个标记正确).

我们最终创建了IActivable接口并扩展了ninject内核(它还为ninject删除了很好的代码级依赖关系,尽管属性仍然存在).

Ian*_*vis 29

Ninject 3

Ninject 3.0现在支持绑定调用中的多个泛型类型,您尝试执行的操作可以在单个链接语句中轻松完成.

kernel.Bind<IService1, IService2>()
      .To<ConcreteService>()
      .InSingletonScope();
Run Code Online (Sandbox Code Playgroud)

Ninject 2

您正在设置两个不同的绑定K => T和L => T. 请求L的实例将返回T的瞬态实例.请求K将返回T的单例实例.

在Ninject 2.0中,对象作用域是绑定到作用域回调的每个服务接口.

当你有

Bind<IFoo>...InSingletonScope();
Bind<IBar>...InSingletonScope();
Run Code Online (Sandbox Code Playgroud)

您正在创建两个不同的范围.

你说"绑定到IFoo将解析为.Get被调用时返回的同一个对象." 并且"绑定到IBar将解析为.Get被调用时返回的同一个对象."

您可以将绑定链接在一起,但是您需要删除IInitializable,因为它会在激活实例时导致重复初始化:

kernel.Bind<IBoo>()
      .To<Foo>()
      .InSingletonScope();
      .OnActivation(instance=>instance.Initialize());

kernel.Bind<IBaz>()
      .ToMethod( ctx => (IBaz) ctx.Kernel.Get<IBoo>() );
Run Code Online (Sandbox Code Playgroud)

要么

kernel.Bind<Foo>().ToSelf().InSingletonScope()
    .OnActivation(instance=>instance.Initialize());
kernel.Bind<IBaz>().ToMethod( ctx => ctx.Kernel.Get<Foo>() );
kernel.Bind<IBoo>().ToMethod( ctx => ctx.Kernel.Get<Foo>() );
Run Code Online (Sandbox Code Playgroud)

为了获得多个接口来解析同一个单例实例.当我看到这样的情况时,我总是要问,如果你有一个有两个职责的单身人士,你的对象是否做得太多了?