5

インターフェイスのメソッドを考えてみましょう:

public Interface IA {
    T[] Get<T>() where T : IB;
}

別の場所では、コンパイル時に既知の n 型に対して、このメソッドを n 回呼び出したいと考えています。次のコードは、私の意図を示しています。

foreach(Type t in new Type[] { typeof(X), typeof(Y), typeof(Z) }) 
{
    InterfaceXYZImplement[] arr = c.Resolve<IA>().Get<t>();
    //...more here
}

さて、foreachループは明らかに型を実行時の値にするので、使用する必要がありますMakeGenericMethod

XYおよびに対してコードを実行できるようにコードを記述しZ、メソッドを 1 回だけ呼び出す方法はありますか?

コードをメソッドにラップしても、問題が上に移動するだけです (これは部分的な解決策ですが、最終的な解決策ではありません)。

4

2 に答える 2

3

dynamicこれは、いくつかの仮定を行い、.NET4 で new キーワードを使用するヘルパー メソッドを使用して実現できます。

基本的に、ソリューションは DLR の機能を利用して、型を使用するパラメーターがdynamic. これが機能するには、次の 2 つのヘルパー メソッドが必要です。

IB[] Get(IA a, Type t)
{
    dynamic dummy = Activator.CreateInstance(t);
    return Get(a, dummy);
}

T[] Get<T>(IA a, T dummy) where T : IB
{
    return a.Get<T>();
}

そして、コードはこれらのヘルパー メソッドの最初のものを呼び出します。

foreach(var t in new Type[] { typeof(X), typeof(Y), typeof(Z) })
{
    IB[] arr = Get(c.Resolve<IA>(), t);
    // do more stuff here
}

ご覧のとおり、このアプローチにはいくつかの欠点があります。

  1. ループ内のタイプごとに、新しいインスタンスが によって作成されActivator.CreateInstance(t)ます。この行は、使用できるパブリック パラメーターなしのコンストラクターが存在し、このコンストラクターが重い処理を行わないことを前提としています。
  2. ループ内の型のいずれかが実装されていない場合、IBこのコードは実行時に例外をスローします。コンパイルエラーは発生しません。
  3. 結果は、特定の型の配列ではなく、常にIBインスタンスの配列になります。
于 2012-05-03T09:59:31.197 に答える
3

拡張メソッドを定義します。

public static class Extensions
{
    public static void Get<T>(this IA a, Action<T[]> action, params Type[] types) where T : IB
    {
        foreach (var type in types)
        {
            var method = a.GetType().GetMethod("Get").MakeGenericMethod(type);
            var ts = (T[])method.Invoke(a, null);
            action(ts);
        }
    }
}

使用する:

a.Get(arr => { 
   // work on result
}, typeof(X), typeof(Y), typeof(Z));
于 2012-05-03T10:10:42.003 に答える