vmg*_*vmg 5 c# dependency-injection unity-container
我正在向我的库添加依赖注入,我使用Unity.我想知道我是否需要采取一些额外的步骤来使Unity Container成为线程安全的.我找到了几篇关于线程安全容器的文章(例如:http://www.fascinatedwithsoftware.com/blog/post/2012/01/04/A-Thread-Safe-Global-Unity-Container.aspx)但我不明白我的项目是否真的需要它.从一方面来看,我不希望由于来自另一方的竞争条件而产生一些令人讨厌的错误,我不知道在什么情况下会出现竞争条件.我想使用Unity与Composition Root模式并在静态构造函数中注册所有类型:
internal static class ConfiguredUnityContainer
{
private static readonly UnityContainer Container = new UnityContainer();
static ConfiguredUnityContainer()
{
Container.RegisterType<IConnectionFactory<SqlConnection>>();
}
public static T Resolve<T>()
{
return Container.Resolve<T>();
}
}
Run Code Online (Sandbox Code Playgroud)
所以,基本上我的问题是:在我使用Unity DI时,在什么情况下我还需要额外的线程安全?我在哪里可以获得竞争条件或线程安全问题?
Ste*_*ven 10
Unity(以及所有常见的容器)在没有注册的并行解析的情况下(由他们的设计者)保证是线程安全的(或者至少是某种类型).换句话说,只要您将注册阶段与解析阶段分开,并且从仅从容器解析的一个点开始,您就可以Resolve从多个线程并行调用而不会出现问题.
事实上,作为一种最佳实践,你应该始终严格地将注册阶段与解决阶段分开,因为这将导致严重的麻烦并且很难找到竞争条件.
这些阶段的这种分离是如此重要,以至于一些DI库(例如Autofac和Simple Injector)会强制使用这种模式(其中Simple Injector是两者中最严格的).Simple Injector文档包含一个非常明确的解释,说明为什么Simple Injector强迫您使用此模型,并解释在您能够更改配置的情况下可能发生的情况.在这里引用部分解释(但你一定要阅读整个解释):
当用户在Web请求期间更改注册时,可以很容易地出现线程安全问题.如果容器在请求期间允许此类注册更改,则其他请求可能会直接受到这些更改的影响(因为通常每个AppDomain应该只有一个Container实例).根据注册的生活方式等因素; 工厂的使用以及对象图的结构如何,另一个请求可能同时获得旧注册和新注册.例如,使用不同的注册替换瞬态注册.如果在将服务注入到图中的多个点的同时解析不同线程的对象图时,该图将包含该抽象的不同实例,同时在同一请求中具有不同的生命周期 - 这不好.
我认为,您链接的文章更多地涉及Service Locator反模式和正确应用依赖注入之间的区别,这意味着只访问组合根中的容器.该文章的作者(拉里斯宾塞)不是很清楚,但在他的作品根中,他创建了一个单独的Unity容器,并在整个应用程序的持续时间内使用它.从某种意义上说,它仍然是"全局的",但他阻止通过应用程序访问该实例(因为这是服务定位器模式).
尽管作者试图在Unity容器周围创建一个线程安全的包装器,但他的尝试是天真的.他所做的是创造周围的每一个锁Register和Resolve方法.这不仅会给予巨大的拥挤在多线程应用程序,它没有解决的注册和对象图后更换情况下,已经建立和缓存,既简单注射器文档时解释发生了什么的问题,而这个统一的问题节目.