Pregunta

Starting with the following:

        string propertyName = TextBoxPropertyToGet.Text;
        ParameterExpression arg = Expression.Parameter(typeof(Item), "x");
        Expression expr = Expression.Property(arg, propertyName);
        LambdaExpression lambda = Expression.Lambda(expr, arg);
        Expression<Func<Item, string>> expression = (Expression<Func<Item, string>>)lambda;

What I was hoping to do:

        ParameterExpression arg = Expression.Parameter(typeof(Item), "x");
        PropertyInfo pi = typeof(Item).GetProperty(propertyName);
        Type pt = pi.PropertyType;
        Expression expr = Expression.Property(arg, pi);
        LambdaExpression lambda = Expression.Lambda(expr, arg);
        Expression<Func<Item, pt>> expression = (Expression<Func<Item, pt>>)lambda;

but I get the error: The type or namespace name 'pt' could not be found (are you missing a using directive or an assembly reference?) On the last line.

I don't want to use:

if(pt == typeof(string))
    Expression<Func<Item, string>>....
else if(pt==typeof(decimal))
    Expression<Func<Item, decimal>>....
....
....

I have also tried:

var expression = Expression.Lambda(
                 Expression.Convert(Expression.Property(
                 arg, propertyName),
                 pt), 
                 arg);

AND

var lambdaMethodParamType = typeof(Func<,>).MakeGenericType(typeof(Item), pt);
var expression = typeof(Expression).GetMethods().First(x => x.Name == "Lambda" && x.IsGenericMethod).MakeGenericMethod(lambdaMethodParamType);

but then I get: The type arguments for method 'System.Linq.Enumerable.Select<TSource,TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,int,TResult>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

basically telling me to do what I don't want to do.

I have tried (as proposed by Servy)

string propertyName = TextBoxPropertyToGet.Text;;
ParameterExpression arg = Expression.Parameter(typeof(Item), "x");
Expression expr = Expression.Property(arg, propertyName);
LambdaExpression lambda = Expression.Lambda(expr, arg);

var x = Queryable.Select(MyContext.Items,(dynamic)lambda);

but this returns empty, and when trying to call var x = Queryable.Select(MyContext.Items,(dynamic)lambda).Distinct(); I get the error 'System.Data.Entity.Infrastructure.DbQuery<string>' does not contain a definition for 'Distinct'

¿Fue útil?

Solución

You need to call Select using reflection, rather than calling it normally, if the generic arguments are not known at compile time. This means getting the Type of Queryable, getting the Select method, choosing the right overload, etc.

The alternative is to use dynamic, which does pretty much the same thing, but handles generating pretty much of that dynamic typing for you:

LambdaExpression lambda = Expression.Lambda(expr, arg);
dynamic query = Queryable.Select(data, (dynamic)lambda);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top