Je vais citer @Ivan Stoev
Le problème est que TResult
besoins soient connus au moment de la compilation, donc linqQuery
(doit) être IQueryable<string>
, ou IQueryable<int>
etc. Il est impossible de résoudre le type de var
lors de l'exécution. Il est possible d'émettre l'appel à Select
dynamiquement, mais tout ce que vous pouvez obtenir sera un IQueryable
non générique, ce qui n'est pas très utile. Vous pouvez jeter un coup d'oeil au paquet DynamicLINQ pour voir comment il répond à ce problème et à d'autres problèmes similaires. Mais même avec cela, il est difficile de travailler avec IQueryable
non typé.
Ensuite, si vous voulez vraiment le faire ... À la fin, il est votre code :-)
Cela peut être mis en mémoire cache:
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();
Puis:
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();
Notez que j'obtiens un IQueryable
non-générique ... Puis je jette ses éléments à object
et fais un ToArray()
, mais vous pouvez faire ce que vous voulez avec. En dessous de la IQueryable
sera fortement typé, donc ce sera un IQueryable<int>
ou un IQueryable<something>
, de sorte que vous pouvez jeter revenir à l'interface « réelle » (IQueryable<T>
hérite de IQueryable
)
Il est très difficile de vous aider sans plein exemple concret . (Je suggère d'utiliser 'List' et 'AsQueryable' pour reproduire ceci.) –
Ce qui est dans vos variables genericFunc, body et source .... – Milney
La version non générique de' Expression.Lambda' ne peut pas être utilisée directement. –