我在我的类中有以下通用方法,它作为仓储模式工作:
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调用返回一个
object
,我需要将其转换为基本的DbSet<pType>
。在我的当前代码中,
genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>
返回null
,表明我无法按照自己的意愿进行强制类型转换,因此我需要具体的返回值类型而不是接口。有什么想法可以实现这一点吗?