在Expression Func中动态设置类型

时间:2014-04-28 18:35:12

标签: c# linq entity-framework linq-to-entities

从以下开始:

        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;

我希望做的事情:

        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;

但我收到错误: The type or namespace name 'pt' could not be found (are you missing a using directive or an assembly reference?)在最后一行。

我不想使用:

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

我也尝试过:

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

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

然后我得到: 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.

基本上告诉我做我不想做的事。

我试过(按照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);

但是这会返回空白,当我尝试拨打var x = Queryable.Select(MyContext.Items,(dynamic)lambda).Distinct();时,我收到错误'System.Data.Entity.Infrastructure.DbQuery<string>' does not contain a definition for 'Distinct'

1 个答案:

答案 0 :(得分:0)

如果在编译时不知道泛型参数,则需要使用反射调用Select,而不是正常调用它。这意味着获取Type Queryable,获取Select方法,选择正确的重载等等。

另一种方法是使用dynamic,这几乎可以做同样的事情,但处理为你生成大部分动态类型:

LambdaExpression lambda = Expression.Lambda(expr, arg);
dynamic query = Queryable.Select(data, (dynamic)lambda);