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

时间:2014-04-04 05:26:57

标签: c# multithreading dependency-injection inversion-of-control structuremap

我有一个使用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();
           });
       }
    }
}

1 个答案:

答案 0 :(得分:7)

一些DI容器(例如(IIIRC)StructureMap)实际上支持 Per Thread 生命周期样式,但这可能无法帮助你,因为它会注入IService Controller在一个线程上,然后在许多其他线程上使用

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

相反,请创建IService的线程安全Adapter/Decorator并将其注入Controller。像这样:

public ThreadSafeService : IService
{
    private readonly IServiceFactory factory;

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

    public void DoSomething()
    {
        this.factory.Create().DoSomething();
    }
}

IServiceFactory可以这样声明:

public interface IServiceFactory
{
    IService Create();
}

如果您实施IServiceFactory以便为IService的每次调用创建Create的新实例,那么您手头就有一个线程安全的实现,因为那里有没有共享状态。

此方法容器无关,可防止漏洞抽象。