【问题标题】:Cast of generic property through reflection通过反射投射通用属性
【发布时间】:2017-06-19 05:51:00
【问题描述】:

我正在尝试按名称检索 DbContext DbSet 属性,但我不知道如何处理泛型参数。

DataSource.Load(IQuerable source) 方法来自外部 dll,我无法修改。

知道我的 DbSet 属性的属性名称(来自实体框架 dbcontext 类)我想将该属性值用作 DataSource.Load 的参数

 public class DataManager
 {

    private MyDbContext _dbContext;

    public DataManager(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }


    public object Load(string propName)
    {
        var source = _dbContext.GetType().GetProperty(entityName).GetValue(_dbContext, null);

        return DataSourceLoader.Load(source);         
    }

    //DataSourceLoader.Load signature:
    //DataSourceLoader.Load<T>(System.Linq.IQueryable<T>)

更新

更清楚一点:DataSourceLoader.Load 从实体集中加载数据;我不关心返回类型,因为它将被序列化并发送到客户端插件。

客户端插件使用 entitySet 名称作为参数通过 ajax 调用请求数据。我不想为我拥有的每个实体集使用不同的方法(或长的 switch 语句)并静态调用 DataSource.Load 方法。

我想解析实体集以在运行时查询

【问题讨论】:

  • 您正在尝试通过提供属性名称来加载实体属性值?
  • @user3292642 源类型取决于 entityName;这是一个 DbSet
  • @grmbl 是的,这就是我想要做的事情

标签: c# entity-framework generics reflection


【解决方案1】:

按照我的理解,问题是如何在运行时调用泛型方法。

通过获取泛型MethodInfo 定义,通过MakeGenericMethod 调用绑定泛型参数并通过Invoke 方法调用它,可以通过反射来做到这一点。

具体的答案取决于许多因素,例如方法是静态还是实例,名称是否唯一(重载)等。您可以在Select Right Generic Method with Reflection 中查看更多详细信息,但最简单的形式是是这样的:

var elementType = ((IQueryable)source).ElementType;
var loadMethod = typeof(DataSourceLoader).GetMethod("Load")
    .MakeGenericMethod(elementType);
return loadMethod.Invoke(null, new object[] { source });

您可以通过使用DLR Fast Dynamic Dispatch and Invocation 功能来避免所有这些复杂情况。在这种情况下,您只需简单地转换为dynamic

return DataSourceLoader.Load((dynamic)source);

【讨论】:

  • 这正是我想要实现的,谢谢
【解决方案2】:

你可以试试这个方法:

public object Load(string setName)
{
    var property = _context.GetType().GetProperties()
        .SingleOrDefault(p => p.PropertyType.IsGenericType
                      && p.PropertyType.GetGenericArguments()[0].GetProperty(setName) != null);
    return property.GetValue(_context) ?? throw new ArgumentOutOfRangeException(setName);
}

【讨论】:

  • 整个目标是不必在方法签名中指定 T 类型
  • 这不能解决问题 var source = _dbContext.GetType().GetProperty(entityName).GetValue(_dbContext, null);已经在我的代码中检索到了值,但是 source 在编译时是 typeof(object) 。我正在尝试将值转换为 IQuerable 以将其用作 DataSource.Load(IQuerable source) 方法的参数
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 2019-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多