如何创建表达式<func <tmodel,tproperty =“”>&gt;没有TProperty类型显式

时间:2018-05-31 16:26:00

标签: c# linq lambda expression

Marc Gravellpost的答案解释了如何创建表达式:

var lambda = CreateExpression<SomeModel, bool>("IsAlive");

可以避免使用显式类型bool,并且该方法从&#34; IsAlive&#34;中获取返回类型。属性?

这样的事情:

var lambda = CreateExpression<SomeModel>("IsAlive");

而lambda将是Expression<Func<SomeModel, bool>>

并在:

var lambda = CreateExpression<SomeModel>("StringProperty");

lambda将是Expression<Func<SomeModel, string>>

1 个答案:

答案 0 :(得分:1)

可以实际上这样做,但类型变得未知。从此方法返回的对象将具有正确的类型Expression<Func<Test, string>>,但在编译时不能强类型

    static LambdaExpression CreateExpression<TModel>(string propertyName)
    {
        var t = typeof(TModel);
        var param = Expression.Parameter(typeof(TModel), "x");
        //get the type for the 2nd generic arg
        var propType = t.GetProperty(propertyName).PropertyType;
        //make the generic type Func<TModel, TProp>
        Type genericFuncType = typeof(Func<,>).MakeGenericType(new Type[] { typeof(TModel), propType });
        //get the Expression.Lambda method
        MethodInfo mi = typeof(Expression).GetMethods().First(a => a.Name == "Lambda" && a.GetParameters().Length == 2);
        //get the Expression.Lambda<Func<TModel, TProp>> method
        MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { genericFuncType });
        //Call Expression.Lambda<Func<TModel, TProp>>
        return (LambdaExpression)mi2.Invoke(null, new object[] { Expression.PropertyOrField(param, propertyName), new ParameterExpression[] { param }});
    }

但请注意,返回类型现在有些未知,需要使用强制转换(或使用动态)。

所以现在你需要更多的代码来投射它。也许这在某种工厂或类似工具中很有用 - 不确定你的用例。

class Program
{
    public static void Main(string[] args)
    {
        var theExpression = CreateExpression<Test>("Name");
        var theExpressionStrongType = theExpression as Expression<Func<Test, string>>;
        //now you could use theExpressionStrongType

        //or do this and go wild. :)
        dynamic d = theExpression;


        Console.ReadKey();
    }
}
class Test
{
    public string Name { get; set; }
}

免责声明:如果您真的想在生产环境中使用它,我会清理代码以获得一次反复类型等等......