0

スレッドセーフな型登録を持つ .net IOC コンテナーはありますか?

アプリケーションの存続期間中に固定されている多数のバインディングがありますが、「スレッドごと」または「リクエストごと」に調整する必要があるいくつかの登録があります。このアプリのスレッドがスレッド プールとの間でリサイクルされると、新しい要求がディスパッチされると、少数の動的 IOC 登録がクリアまたは上書きされます。

明確にするために、以下は、コンテナーの "モジュール" または "レジストリ" の概念と WCF サービスを組み合わせた Unity ベースのサンプル コードです。

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()はアプリケーションの存続期間中に 1 回呼び出されますが、ReInitialize()WCF サービス要求ごとに呼び出されます。にReInitialize()は、実行される WCF 操作の名前と、提供されるパラメーターが指定されます。完了後、サービス インスタンスでReInitialize()最後の UnityBuildUp()呼び出しが行われ、サービス操作が実行されます。

例がさらに示すように、サービス呼び出しに関する情報は、DataAccess インスタンスがインスタンス化される DB 接続文字列を決定するために使用されます。

この動作を作成するために、当初は、一意のバインディングが必要なリクエストごとに Unity 子コンテナーを作成することを計画していました。これが、呼び出しに childContainer パラメーターが渡された理由です。しかし、それ自体がスレッド セーフではないことがReInitialize()わかりました。CreateChildContainer実際、.net IOC コンテナーのスレッド セーフの主張を見つけるのは難しいことがわかりました ( Autofac を除いて、かなり明確になります)。

スレッドセーフな登録を許可するコンテナーは、ConcurrentDictionaryまたは不変の 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 コンテナーはありますか?

4

1 に答える 1

0

編集:

Autofacには機能があります

すべてのコンテナ操作は、複数のスレッド間で安全に使用できます。

解決コンテキスト オブジェクトはシングル スレッドであり、依存関係の解決操作中以外は使用しないでください。

コンテナ階層メカニズムは、任意のファクトリ/コンテナ コンポーネントのコンポーネント登録のローカル コピーを維持することにより、ロックをさらに減らします。初期登録コピーが作成されると、「内部」コンテナーを使用するスレッドは、他のスレッドをブロックすることなく、そのようなコンポーネントを作成またはアクセスできます。

Autofacを使用して、スレッドに固有のサービスを登録できます。

スレッドセーフな型 次の型は、複数のスレッドによる同時アクセスに対して安全です。

容器

コンポーネントレジストリ

Disposer ( IDisposerのデフォルト実装)

LifetimeScope ( ILifetimeScopeのデフォルト実装)

これらのタイプは、実質的にすべての実行時/解決シナリオをカバーしています。

ContainerBuilderは、構成時のシングルスレッド アクセス用に設計されています

于 2013-10-30T18:19:28.717 に答える