我正在使用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
,但我仍然會收到此錯誤。我究竟做錯了什麼?
我引用@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>
,因此您可以將其IQueryable<T>
回“真實”接口( IQueryable<T>
繼承自IQueryable
)