2011-11-01 122 views
0

我使用Ninject,但是这应该适用于任何IoC。 我有一个后台线程运行的单例,线程运行整个程序的生命周期。每5分钟后台线程开始几个工作人员。这些工人使用的是autofac需要处理依赖关系的单例解决方案

Func<IEnumerable<IWorker>> 

注入但这只是利用了一些照顾的问题,让我解释一下,我的一些工人必须依赖于存储库和每个仓库都依赖于它有一个实体框架上下文线程范围(线程结束时将被处理)。这意味着当autofac被执行时,我得到一个工作者列表,他们的作用域将在与程序具有相同生命周期的后台线程上,并不适合拥有整个应用程序的EF上下文。每个工作人员的Execute方法都是在一个单独的线程中执行的,但这样做并不重要,因为Ninject仍然只会监听永远不会结束的主后台线程。

,如果你问我,我有一个非常丑陋的方式解决了这个,现在我注入一个没有通用的工厂

Func<Type, object> 

我然后问大会返回IWorker接口和我的所有具体类型,然后使用工厂方法在每个工作线程中调用它们(这意味着范围将只用于工作线程而不是背景thead),这是有效的,但它很丑,我不能存根IWorkers,这意味着我不能运行我的单元测试任何更多。

你们对我有一个很好的解决方案吗? :d感谢

编辑:感谢您的帮助雷莫,指定范围的部分现在的作品,但原来的问题依然存在。这是我的测试代码

使用WorkManager

internal class WorkflowManager : IWorkflowManager 
{ 
    private readonly Func<IWorker> testWorker; 
    private BackgroundWorker backgroundWorker; 

    public WorkflowManager(Func<IWorker> testWorker) 
    { 
     this.testWorker = testWorker; 
    } 

    public void Start() 
    { 
     backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += DoBackgroundWork; 
     backgroundWorker.RunWorkerAsync(); 
    } 

    public void Stop() 
    { 

    } 

    private void DoBackgroundWork(object sender, DoWorkEventArgs e) 
    { 
     var test = testWorker(); 
    } 

} 

它结合

kernel.Bind<IWorkflowManager>().To<WorkflowManager>().InSingletonScope(); 

工人

internal class TestWorker : IWorker, IDisposable 
{ 
    public TestWorker() 
    { 
     System.Diagnostics.Debug.WriteLine("Contructed!"); 
    } 

    ~TestWorker() 
    { 
     System.Diagnostics.Debug.WriteLine("Deconstructed!"); 
    } 

    public void Dispose() 
    { 
     System.Diagnostics.Debug.WriteLine("Disposed!"); 
    } 

} 

绑定

kernel.Bind<IWorker>().To<TestWorker>().InCallScope(); 

只有构造函数被调用...:/

回答

3

使用https://github.com/ninject/ninject.extensions.namedscope/wiki/InCallScope。使用此作用域将在工作人员从缓存收集或释放垃圾时处置依赖关系。

像这样设置应用程序。下一个版本不再需要此解决方法。

public static class NinjectMVC3 
{ 
    private static readonly Bootstrapper bootstrapper = new Bootstrapper(); 

    /// <summary> 
    /// Starts the application 
    /// </summary> 
    public static void Start() 
    { 
     DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule)); 
     DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule)); 
     bootstrapper.Initialize(CreateKernel); 
     bootstrapper.Kernel.Rebind<IResolutionRoot>().To<ContextPreservingResolutionRoot>(); 
    } 

    /// <summary> 
    /// Stops the application. 
    /// </summary> 
    public static void Stop() 
    { 
     bootstrapper.ShutDown(); 
    } 

    /// <summary> 
    /// Creates the kernel that will manage your application. 
    /// </summary> 
    /// <returns>The created kernel.</returns> 
    private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     RegisterServices(kernel); 
     return kernel; 
    } 

    /// <summary> 
    /// Load your modules or register your services here! 
    /// </summary> 
    /// <param name="kernel">The kernel.</param> 
    private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Unbind<IResolutionRoot>(); 
    }   
} 
+0

感谢您输入雷莫,我有ninject的nuget版本2.2,它没有那个范围? – Anders

+0

如果我从具有InCallScope的nuget下载了命名范围扩展,它会崩溃并且说IResolutionRoot定义了两次,看起来像这两个lib都试图注册它?非常容易混淆这个..:D – Anders

+0

你使用哪些扩展?或者你自己注册IResolutionRoot? –

相关问题