多线程注册

时间:2013-10-30 18:05:13

标签: .net ninject unity-container structuremap autofac

是否有任何具有线程安全类型注册的.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除外)。

我怀疑允许线程安全注册的容器会使用ConcurrentDictionaryimmutable 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容器具有线程安全注册?

1 个答案:

答案 0 :(得分:0)

编辑:

Autofac具有

功能

所有容器操作在多个线程之间使用是安全的。

解析上下文对象是单线程的,除非在依赖项解析操作过程中,否则不应使用它。

容器层次结构机制通过维护任何工厂/容器组件的组件注册的本地副本,进一步减少了锁定。完成初始注册副本后,使用“内部”容器的线程可以创建或访问此类组件,而不会阻止任何其他线程。

您可以使用 Autofac 注册特定于某个主题的服务。

线程安全类型 以下类型对于多个线程的并发访问是安全的:

<强>容器

<强> ComponentRegistry

处置器 IDisposer的默认实施

LifetimeScope ILifetimeScope的默认实施

这些类型几乎涵盖了所有运行时/解析方案。

ContainerBuilder 专为配置时的单线程访问而设计