通过反思铸造通用财产

时间:2017-06-19 05:51:01

标签: c# entity-framework generics reflection

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

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

知道我的DbSet prop的属性名称(来自实体框架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 name作为参数通过ajax调用请求数据。我不想为我拥有的每个实体集使用不同的方法(或long switch语句),并静态调用DataSource.Load方法。

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

2 个答案:

答案 0 :(得分:2)

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

通过获取通用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);

答案 1 :(得分:0)

您可以尝试使用此方法:

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