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)
有些DI容器(如(IIIRC)StructureMap)实际上支持每个线程一生的风格,但是这可能不会帮助你,因为它会注入IService到Controller上一个线程,然后用它在许多其他线程.
我建议将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)
如果你实现IServiceFactory它IService为每次调用创建一个新实例Create,你就有了一个线程安全的实现,因为没有共享状态.
这种方法与容器无关,可以防止漏洞抽象.