2

Simple Injector を使用して、e コマース プロジェクト用のプラグイン システムを構築しています。私はaとRegisterAlla のすべての実装を登録するために使用しています(およびさらに多くの場合)。IPaymentProviderIResourceRegistrar

しかし、これは毎回新しいインスタンスを作成します。ここでは、RegisterSingleタイプごとに使用することをお勧めします。しかし、この場合、これをどのように達成するのでしょうか?

private static void RegisterMultipleUnderOneInterface(
    Container container, string name)
{
    IEnumerable<Type> pluginRegistrations =
        from dll in finder.Assemblies
        from type in dll.GetExportedTypes()
        where type.GetInterfaces().Any(i => i.Name == name)
        where !type.IsAbstract
        where !type.IsGenericTypeDefinition
        select type;

    if (pluginRegistrations.Any())
    {
        var @interface =
            pluginRegistrations.ElementAt(0).GetInterfaces()
            .First(i => i.Name == name);

        foreach (Type type in pluginRegistrations)
        {
            // HERE: register the type single somehow. 
        }

        container.RegisterAll(@interface, pluginRegistrations);
    }
} 

container.RegisterSingle(type)IPaymentProvider同じインターフェイス (または)に固有の型であるため、機能しませんIResourceRegistrarIPaymentProvider実装クラスには、パラメーターなしのコンストラクター (パラメーターあり) がありIResourceRegistrarます。

私はこのようなことをしたくありません。むしろ、IoC コンテナーの目的を無効にします。

var constructor = type.GetConstructors()[0];

switch (name)
{
    case "IResourceRegistrar":
        container.RegisterSingle(type, () =>
        {
            return constructor.Invoke(new object[
            {
                container.GetInstance<ILanguageService>()});
            });
        break;
    case "IPaymentProvider":
    default:
        container.RegisterSingle(type, () =>
        {
            return constructor.Invoke(new object[] { });
        });
        break;
}

これらを醜いスイッチなしでシングルトンとして登録する方法は?

4

1 に答える 1

2

誤解しているかもしれませんが、RegisterSingle は動作するはずです。これを行うことができるはずです:

var types = ...

container.RegisterAll<IInterface>(types);

foreach (var type in types)
{
    container.RegisterSingle(type, type);
}

アップデート:

したがって、あなたがやろうとしているのは、次の構成を自動化することです。

// A, B, C and D implement both I1 and I2.
container.RegisterSingle<A>();
container.RegisterSingle<B>();
container.RegisterSingle<C>();
container.RegisterSingle<D>();

container.RegisterAll<I1>(typeof(A), typeof(B), typeof(C), typeof(D));
container.RegisterAll<I2>(typeof(A), typeof(B), typeof(C), typeof(D));

これは通常、これを自動化する方法です。次の 4 つの手順を実行します。

  1. 登録するすべてのタイプを検索します。
  2. 見つかった型をシングルトンとして登録します。
  3. タイプのリストを のコレクションとして登録しますI1
  4. タイプのリストを のコレクションとして登録しますI2

これは次のようになります。

// using SimpleInjector.Extensions;

Type[] singletons = FindAllTypesToRegister();

foreach (Type type in singletons)
{
    container.RegisterSingle(type, type);
}

container.RegisterAll(typeof(I1), singletons);
container.RegisterAll(typeof(I2), singletons);

ただし、これを 2 つのステップに分割し、各ステップを処理できる 1 つのジェネリック メソッドを作成しようとしているため、具体的なシングルトン タイプが既に登録されている場合は無視する必要があります。次のいずれかの方法でこれを行うことができます。

  • からスローされた例外をキャッチして登録を無視しRegisterSingleます。
  • container.Options.AllowOverridingRegistrations = true呼び出す前に設定して、既存の登録を上書きしますRegisterSingle(後で無効にするのが最も安全です)。
于 2012-12-03T19:14:01.893 に答える