3

クラス内に、リポジトリ パターンとして機能する次のジェネリック メソッドがあります。

public DbSet<T> GetAll<T>() where T : class
{
  return dbContext.Set<T>();
}

ここで、特定のインターフェイス ( ) を実装するエンティティ クラスに属する、データベース内のすべてのエンティティのリストを取得したいと考えていますIChangeTrackingEntity。したがって、現在、これに準拠する約 10 の特定のテーブル/クラスがありますが、これらのテーブルに 10 個のハードコードされた呼び出しを追加したくないので、代わりにリフレクションを使用して実行したいと思います (実装するクラスがこのインターフェイスは将来変更されるので、ここでも変更してコードを相互に依存させることを覚えておく必要はありません)。

動作するが、私が望まないコードの例:

var result = new List<IChangeTrackingEntity>();
using ( var repository = new DbRepository())
{
  result.AddRange( repository.GetAll<FirstTypeThatImplementsInterface>() );
  result.AddRange( repository.GetAll<SecondTypeThatImplementsInterface>() );
  result.AddRange( repository.GetAll<ThirdTypeThatImplementsInterface>() );
  result.AddRange( repository.GetAll<FourthTypeThatImplementsInterface>() );
  result.AddRange( repository.GetAll<FifthTypeThatImplementsInterface>() );
}
return result;

私はかなり近づいていますが、Invokeバックの結果を正しい型にキャストする最後の部分を機能させることができません。私が現在得たものはこれです:

var result = new List<IChangeTrackingEntity>();
var method = typeof (DbRepository).GetMethod("GetAll");
using ( var repository = new DbRepository())
{
  foreach (var p in typeof(AnchorDbContext).GetProperties())
  {
    if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
    {
      var pType =  p.PropertyType.GetGenericArguments()[0];
      if (pType.GetInterface("IChangeTrackingEntity") != null)
      {
        var genericMethod = method.MakeGenericMethod(new[] {pType});
        result.AddRange(genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>);
      }
    }
  }
  return result;
}

objectInvoke 呼び出しが aを返し、それを基本的に にキャストする必要があるという上記の問題DbSet<pType>

現在のコードでgenericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>null、必要に応じて戻り値をキャストできないことを示す戻り値が返されるため、私が考えるインターフェイスではなく、特定の戻り値の型が必要です。

これを達成する方法のアイデアはありますか?

4

3 に答える 3

3

にキャストしてみてくださいIEnumerable<IChangeTrackingEntity>。これは、共分散/反分散のために機能するはずです。

于 2012-05-30T13:38:04.417 に答える
1

この特定の問題についてはよくわかりませんが、 から にキャストしているようDbSet<T> where T : IChangeTrackingEntityですDbSet<IChangeTrackingEntity>。これは、共分散または反分散と呼ばれ (私は常にそれらの間で混乱します...)、DbSet<>がインターフェースである場合にのみ機能します。したがって、ここではキャストは機能しません。可能であれば同等のインターフェイスを使用するか、DbSet where T: を受け入れて何らかの方法でIChangeTrackingEntity返すジェネリック メソッドを作成しますDbSet<IChangeTrackingEntity>。私はそれを行う方法を考え出し、私の前に誰も答えていない場合は答えを投稿しようとします (このサイトではありそうもない:P)

于 2012-05-30T13:32:58.017 に答える
0

この質問を見る必要があると思います:

MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);
于 2012-05-30T13:30:51.257 に答える