我正在使用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
,但我仍然会收到此错误。我做错了什么?
答案 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
)