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;
}

上面的问题是 Invoke 调用返回 a object,我需要将其转换为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 : IChangeTrackingEntityto 转换DbSet<IChangeTrackingEntity>。这称为协变或逆变(我总是在它们之间感到困惑......),它只有在DbSet<>是一个接口时才有效。所以,铸造在这里不起作用。如果可以,请使用等效接口,或者创建一个接受 DbSet where T:IChangeTrackingEntityDbSet<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 回答