1

私は今次のことをしています

container.Register<IDatabaseMapper<User>, DatabaseMapper<User, OracleException>>();
container.Register<IDatabaseMapper<Desk>, DatabaseMapper<Desk, OracleException>>();
container.Register<IDatabaseMapper<Commodity>, DatabaseMapper<Commodity, OracleException>>();

でもこういうことをしたい

container.RegisterOpenGeneric(typeof(IDatabaseMapper<>), typeof(DatabaseMapper<,OracleException>));

これはどういうわけか可能ですか?

4

2 に答える 2

2

これは可能ですか?はいといいえ :-)

typeof(DatabaseMapper<,OracleException>)は有効な C# コードではありません。すべてのジェネリック型引数を指定するか、まったく指定しないかのいずれかです。したがって、欠落している型引数を でContainer埋める必要があることを に通知する方法はありません。いいえ、これはできません。TExceptionOracleException

しかし、はい、もちろんこれを行うことができます:-)。登録でその型OracleExceptionDatabaseMapper<T>を継承して使用するクラスを作成するだけです。DatabaseMapper<T, OracleException>

// Helper class
public class OracleExceptionDatabaseMapper<T>
    : DatabaseMapper<T, OracleException>
{
}

// Registration
container.RegisterOpenGeneric(typeof(IDatabaseMapper<>),
    typeof(OracleExceptionDatabaseMapper<>));

このようにして、特定の実装にはジェネリック型が 1 つしかなく、それを特定のサービス インターフェイスの単一のジェネリック型引数にマップできます。

アップデート

Simple Injector 2.4 以降、部分的なオープン ジェネリック型を登録することが可能になりましたが、これは C# ではまだサポートされていないため、次のように部分的なオープン ジェネリック型を手動で作成する必要があります。

Type databaseMapperType = typeof(DatabaseMapper<,>).MakeGenericType(
    typeof(DatabaseMapper<,>).GetGenericArguments().First(),
    typeof(OracleException));

container.RegisterOpenGeneric(typeof(IDatabaseMapper<>), databaseMapperType);
于 2012-03-02T17:48:24.053 に答える
1

完全を期すために、未登録の型解決を使用してこれを行う方法の例を次に示します。

container.ResolveUnregisteredType += (s, e) =>
{
    var serviceType = e.UnregisteredServiceType;

    if (serviceType.IsGenericType &&
        serviceType.GetGenericTypeDefinition() == typeof(IDatabaseMapper<>))
    {
        Type argument = serviceType.GetGenericArguments()[0];

        var closedDatabaseMapperType = typeof(DatabaseMapper<,>)
            .MakeGenericType(argument, typeof(OracleException));

        var registration =
            container.GetRegistration(closedDatabaseMapperType, true);

        e.Register(registration.BuildExpression());
    }
};

このResolveUnregisteredTypeイベントは、登録されていない型が要求されるたびにコンテナーによって呼び出されます。これにより、そのタイプを登録する最後のチャンスが得られます。提供されている には、その型を登録できるUnregisteredTypeEventArgs2 つのメソッド オーバーロードが含まれています (または を使用)。RegisterFunc<T>Expression

上記のコードは、要求されたサービス タイプが であるかどうかを確認し、そうである場合は、 サービス タイプの実際のタイプに置き換えられる をIDatabaseMapper<T>構築します。その型を使用して、その型の登録がコンテナーから要求されます。その登録オブジェクトのメソッドを使用して、その の新しいインスタンスの作成を記述する式ツリーを構築できます。メソッドを使用して登録されたこの式 ID は、を の作成に効果的にマップします。DatabaseMapper<T, OracleExpression>TBuildExpressionDatabaseMappere.RegisterIDatabaseMapper<T>DatabaseMapper<T, OracleException>

重要: 未登録の型解決の使用は、フォールバック オプションとしてのみ使用する必要があると思います。これは、問題を解決するためのより簡単な方法 (他の回答で示したものなど) がしばしばあるためです。シナリオ (たとえば、DatabaseMapper<T, TException>が封印されている場合)。

于 2012-03-03T02:03:20.437 に答える