IOC DI多线程生命周期范围在后台任务中

Cha*_*tch 5 c# structuremap multithreading dependency-injection inversion-of-control

我有一个使用IOC和DI来创建和注入服务的应用程序.

我有一个服务层来处理一些业务逻辑,在服务层我有一个与数据库通信的存储库.该存储库使用的是非线程安全的DataContext.

我想使用后台任务异步运行服务上的一些函数,但是知道这会导致存储库出现问题.因此,我希望为每个创建的后台线程创建存储库.这是如何实现的?我正在使用StructureMap作为IoC.

public class Service : IService
{
    IRepository _repository;

    public Service(IRepository repository)
    {
        this._repository = repository;
    }

    public void DoSomething()
    {
        // Do Work
        _repository.Save();
    }
}


public class Controller
{
    IService _service;

    public Controller(IService service)
    {
        this._service = service;
    }

    public Action DoSomethingManyTimes()
    {
       for(int i =0; i < numberOfTimes; i++)
       {
           Task.Factory.StartNew(() =>
           {  
               _service.DoSomething();
           });
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ann 7

有些DI容器(如(IIIRC)StructureMap)实际上支持每个线程一生的风格,但是这可能不会帮助你,因为它会注入IServiceController上一个线程,然后它在许多其他线程.

我建议将Controller实现保留原样,因为特定实现IService不是线程安全的,这是一个实现细节.

相反,创建一个线程安全的适配器/装饰IService,并注入到这一点Controller.像这样的东西:

public ThreadSafeService : IService
{
    private readonly IServiceFactory factory;

    public ThreadSafeService(IServiceFactory factory)
    {
        this.factory = factory;
    }

    public void DoSomething()
    {
        this.factory.Create().DoSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

IServiceFactory 可以像这样声明:

public interface IServiceFactory
{
    IService Create();
}
Run Code Online (Sandbox Code Playgroud)

如果你实现IServiceFactoryIService为每次调用创建一个新实例Create,你就有了一个线程安全的实现,因为没有共享状态.

这种方法与容器无关,可以防止漏洞抽象.

  • 但是,如果您需要为许多不同的接口实现上述模式,您可能需要研究动态拦截(AKA AOP); 这是我给出的概述说明:http://channel9.msdn.com/Events/GOTO/GOTO-2011-Copenhagen/CPH-Aspect-Oriented-Programming-with-Dependency-Injection (2认同)