2017-08-07 155 views
0

我希望在应用程序启动后立即启动使用依赖注入(ninject)的单例类。单例类位于域图层(类库)中 - Domain.Concrete.Operations。我在WebUI层(MVC)中使用这个类。 我一直在初始化我计划在Application_Start方法中启动的服务的静态构造函数中的依赖项。什么是正确的做法?无法初始化依赖关系。使用依赖注入的单例类(Ninject)

Singleton类:

namespace Domain.Concrete.Operations 
{ 
    public sealed class SingletonClass 
    { 
     private IInterface1 _iInterface1; 
     private IInterface2 _iInterface2; 

     public SingletonClass(IInterface1 iInterface1, IInterface2 iInterface2) 
     { 
      this._iInterface1 = iInterface1; 
      this._iInterface2 = iInterface2; 

      StartAllOperations(); 
     } 

     public void StartAllOperations() 
     { 

     } 
    } 
} 

NinjectDependencyResolver:

namespace WebUI.Infrastructure 
{ 
    public class NinjectDependencyResolver : IDependencyResolver 
    { 
     IKernel kernel; 

     public NinjectDependencyResolver(IKernel kernelParam) 
     { 
      kernel = kernelParam; 
      AddBindings(); 

     } 

     public object GetService(Type serviceType) 
     { 
      return kernel.TryGet(serviceType); 
     } 

     public IEnumerable<object> GetServices(Type serviceType) 
     { 
      return kernel.GetAll(serviceType); 
     } 

     private void AddBindings() 
     { 
      kernel.Bind<IInterface1>().To<Class1>(); 
      kernel.Bind<IInterface2>().To<Class2>(); 

      kernel.Bind<SingletonClass>().To<SingletonClass>().InSingletonScope(); 
     } 
    } 
} 

据我理解这个代码将有助于恢复SigletonClass的同一个实例:

kernel.Bind<SingletonClass>().To<SingletonClass>().InSingletonScope(); 

服务App_Start:在的Application_Start(Global.asax.cs中)

namespace WebUI.App_Start 
{ 
    public class OperationManagerService 
    { 

     private IInterface1 _iInterface1; 
     private IInterface2 _iInterface2; 

     static OperationManagerService() //static constructor cannot have parameters 
     { 
      _iInterface1 = //how to initialize 
      _iInterface2 = //interfaces here? 
     } 

     public static void RegisterService() 
     { 
      new SingletonClass(_iInterface1, _iInterface2); 
     } 
    } 
} 

注册服务:

namespace WebUI 
{ 
    public class MvcApplication : System.Web.HttpApplication 
    { 


     protected void Application_Start() 
     { 
      AreaRegistration.RegisterAllAreas(); 
      GlobalConfiguration.Configure(WebApiConfig.Register); 
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 
      OperationManagerService.RegisterService(); 
     } 
    } 
} 

UPDATE:

我必须承认,我能够像这样初始化依赖关系,但是我只能在控制器中使用OperationManagerService类。 不在Application_Start!

  static OperationManagerService(IInterface1 iInterface1, IInterface2 iInterface2) 
     { 
      _iInterface1 = iInterface1; 
      _iInterface2 = iInterface2; 
     } 

这使我想到,我不能使用的Application_Start注射Ninject。如果这是真的,那么创建一个应该在启动时加载的类的正确位置在哪里?

回答

0

您正在尝试混合Singleton patternNinject's Singleton Scope,这会混淆谁试图构建什么时候。尝试使用DI时不要使用旧的Singleton模式。 DI的一半是管理其包含的对象的生命周期(范围)。您可以通过指定.InSingletonScope()来完成此操作。

现在,在将注入依赖关系注入启动特性的问题中:您需要允许Ninject构造OperationManagerService以获得由Ninject提供的依赖关系。为此,请将其注册到Singleton范围内,就像您使用SingletonClass一样。 第一次它是从Ninject容器中请求的,它将被构造并注入必要的参数。 Singleton范围仅告诉Ninject只构造一个实例。

但是,您似乎希望在启动过程中构建它?如果这是一项要求,则需要有所要求。最简单的解决办法是结合之后获得它:

private void AddBindings() 
{ 
    kernel.Bind<IInterface1>().To<Class1>(); 
    kernel.Bind<IInterface2>().To<Class2>(); 

    kernel.Bind<SingletonClass>().ToSelf().InSingletonScope(); 
    kernel.Bind<OperationManagerService>().ToSelf().InSingletonScope(); 

    kernel.Get<OperationManagerService>(); // activate 

} 

如果你发现自己这样做了很多,我用一个简单的“自动启动”模式:

public interface IAutoStart() 
{ 
    void Start(); 
} 

public class SomeClassThatStarts : IAutoStart 
{ 
    public void Start() 
    { 
     Console.Log("Starting!"); 
    } 
} 

public class AutoStartModule : Ninject.Modules.NinjectModule 
{ 
    public override void Load() 
    { 
     foreach(var starter in Kernel.GetAll<IAutoStart>()) 
     { 
      starter.Start(); 
     } 
    } 
} 

注册AutoStartModule最后在你的内核中,任何IAutoStart都会加载任何依赖项并启动。

+0

非常感谢Dave!是的,我已经添加了kernel.Get ();到我的AddBinding方法,并且它在启动时创建了需要的实例。我还会阅读你附加到你的文章的链接!再次感谢!祝你今天愉快!!! –

+0

很高兴我能帮到你。请标记为已接受。 –