无法从使用

时间:2017-05-03 08:41:21

标签: c# linq lambda expression expression-trees

我正在使用LambdaExpression动态选择列:

var property = "power_usage"; // I set this dynamically.
var entityType = typeof(system_state);
var prop = entityType.GetProperty(property);
var source = Expression.Parameter(entityType, "ss");

var func = typeof(Func<,>);
var genericFunc = func.MakeGenericType(typeof(system_state), prop.PropertyType);

var linqQuery = context.system_state
            .Where(ss => ss.time_stamp >= StartDate && ss.time_stamp <= EndDate)
            .Select(genericFunc, Expression.PropertyOrField(source, property), source);

变量genericFunc应该定义delegateType,但我仍然会收到此错误。我做错了什么?

1 个答案:

答案 0 :(得分:2)

我引用@Ivan Stoev

  

问题是TResult需要在编译时知道,因此linqQuery(必须)是IQueryable<string>IQueryable<int>等。它不是可以在运行时解析var的类型。它可以动态地发出对Select的调用,但你可以得到的只是非通用IQueryable,这不是那么有用。您可以查看DynamicLINQ包,看看它是如何解决这个问题和类似问题的。但即便如此,使用无类型的IQueryable也是一种痛苦。

然后,如果你真的想这样做......最后它是你的代码: - )

这可以缓存:

private static readonly MethodInfo selectT = (from x in typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static)
                                                where x.Name == nameof(Queryable.Select) && x.IsGenericMethod
                                                let gens = x.GetGenericArguments()
                                                where gens.Length == 2
                                                let pars = x.GetParameters()
                                                where pars.Length == 2 &&
                                                    pars[0].ParameterType == typeof(IQueryable<>).MakeGenericType(gens[0]) &&
                                                    pars[1].ParameterType == typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(gens))
                                                select x).Single();

然后:

var property = "power_usage"; // I set this dynamically.
var entityType = typeof(system_state);
var prop = entityType.GetProperty(property);
var source = Expression.Parameter(entityType, "ss");

var func = typeof(Func<,>);
var genericFunc = func.MakeGenericType(typeof(system_state), prop.PropertyType);

var baseQuery = context.system_state
            .Where(ss => ss.time_stamp >= StartDate && ss.time_stamp <= EndDate);

var exp = Expression.Lambda(Expression.Property(source, prop), source);

MethodInfo select = selectT.MakeGenericMethod(entityType, prop.PropertyType);

IQueryable query = (IQueryable)select.Invoke(null, new object[] { baseQuery, exp });

var result = query.Cast<object>().ToArray();

请注意,我获得了非通用IQueryable ...然后我将其元素投射到object并执行ToArray(),但你可以做任何你想做的事情用它。 IQueryable下面会有强类型,因此它会是IQueryable<int>IQueryable<something>,因此您可以将其强制转换为&#34;真实&#34; interface(IQueryable<T>继承自IQueryable