使用反射在方法调用上获取正确的返回值

本文关键字:获取 返回值 调用 反射 方法 | 更新日期: 2023-09-27 18:35:58

我的类中有以下泛型方法,用作存储库模式:

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

上面的问题是调用返回一个object,我需要将其转换为基本上DbSet<pType>

在我当前的代码中,genericMethod.Invoke(repository, null) as DbSet<IChangeTrackingEntity>返回null指示我无法根据需要转换返回值,因此我需要特定的返回值类型,而不是我认为的接口。

知道如何做到这一点吗?

使用反射在方法调用上获取正确的返回值

尝试投射到IEnumerable<IChangeTrackingEntity> .由于协变/逆变,这应该有效。

我对这个具体问题了解不多,但你似乎正在从DbSet<T> where T : IChangeTrackingEntity投射到DbSet<IChangeTrackingEntity>.这被称为协方差或逆变(我总是在它们之间混淆......),它只有在DbSet<>是一个接口时才有效。所以,铸造在这里不起作用。如果可以,请使用等效的接口,或者创建一个接受 DbSet 的泛型方法,其中 T: IChangeTrackingEntity并以某种方式返回DbSet<IChangeTrackingEntity>。我会尝试弄清楚如何做到这一点,并在我之前没有人回答过答案(在这个网站上不太可能:P)

我想

你需要看到这个问题:

MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);