是否有任何具有线程安全类型注册的.net IOC容器?
我有许多在应用程序生命周期内修复的绑定 - 但是有一些注册需要在“每个线程”或“每个请求”的基础上进行调整。当此应用程序的线程被回收到线程池或从线程池中回收时,在调度新请求时,将清除或覆盖少量动态IOC注册。
为了澄清,下面是基于Unity的示例代码,它将WCF服务与容器“模块”或“注册表”的概念相结合。
public class AccountServiceRegistry : UnityContainerExtension, IBindingOverride
{
//From UnityContainerExtension
protected override void Initialize()
{
Container.RegisterType<IAccountService, AccountService>();
}
//From IBindingOverride
public void ReInitialize(IUnityContainer child, string action, object[] parms){
child.RegisterType<AccountService>(new InjectionProperty("log"), new InjectionProperty("dao"));
child.AddNewExtension<DataAccessRegistry>();
string connectionString = action == "GetMoreData" ? "Alpha" : "Bravo";
child.Configure<IDataAccessConfig>().WithConnection(connectionString);
}
}
在此示例中,AcccountServiceRegisty
方法Initialize()
将在应用程序的生命周期内调用一次,但ReInitialize()
将在每个WCF服务请求中调用。 ReInitialize()
被赋予将要执行的WCF操作的名称以及将提供的参数。 ReInitialize()
完成后,在服务实例上进行最后一次Unity BuildUp()
调用,然后执行服务操作。
如示例进一步说明的那样,有关服务调用的信息用于确定将实例化DataAccess实例的数据库连接字符串。
要创建此行为,我最初计划为每个需要唯一绑定的请求创建Unity子容器。这就是ReInitialize()
调用传入了childContainer参数的原因。但后来我发现CreateChildContainer
本身似乎不是线程安全的。事实上,我发现很难找到任何.net IOC容器的线程安全声明(Autofac, which makes it rather clear除外)。
我怀疑允许线程安全注册的容器会使用ConcurrentDictionary或immutable collections。我们会看到。
另一方面,如果我绝对不得不避免这种动态的,多线程的注册过程 - 我想我会进行类型到委托的注册而不是类型到注册的注册。这样,委托可以动态决定创建什么,而不是绑定本身是动态的。在这种情况下,先前的示例代码会将所有注册从ReInitialize()
方法移动到Initialize()
方法,而IDataAccessConfig
实现将更改为如下所示:
public class DataAccessRegistry: UnityContainerExtension, IDataAccessConfig
{
[ThreadStatic]
string connection;
protected override void Initialize()
{
Container.RegisterType<IDataAccess>(new InjectionFactory(c => new DataAccess(connection)));
}
public IDataAccessConfig WithConnection(string connection)
{
this.connection = connection;
return this;
}
}
上述示例的关键部分是[ThreadStatic]
,可确保多个线程可以安全地调用WithConnection()
。
但这不会改变我的问题 - 是否有一个.net容器具有线程安全注册?
答案 0 :(得分:0)
编辑:
Autofac具有
功能所有容器操作在多个线程之间使用是安全的。
解析上下文对象是单线程的,除非在依赖项解析操作过程中,否则不应使用它。
容器层次结构机制通过维护任何工厂/容器组件的组件注册的本地副本,进一步减少了锁定。完成初始注册副本后,使用“内部”容器的线程可以创建或访问此类组件,而不会阻止任何其他线程。
您可以使用 Autofac 注册特定于某个主题的服务。
线程安全类型 以下类型对于多个线程的并发访问是安全的:
<强>容器强>
<强> ComponentRegistry 强>
处置器( IDisposer的默认实施)
LifetimeScope ( ILifetimeScope的默认实施)
这些类型几乎涵盖了所有运行时/解析方案。
ContainerBuilder 专为配置时的单线程访问而设计