【问题标题】:How to create Expression<Func<TModel, TProperty>> without TProperty type explicit如何在没有显式 TProperty 类型的情况下创建 Expression<Func<TModel, TProperty>>
【发布时间】:2018-06-01 01:28:59
【问题描述】:

Marc Gravell 在这个post 中的答案解释了如何创建这样的表达式:

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

是否可以避免显式类型 bool 并且该方法从“IsAlive”属性获取返回类型?

类似这样的:

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

而 lambda 将是 Expression&lt;Func&lt;SomeModel, bool&gt;&gt;

在:

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

lambda 将是 Expression&lt;Func&lt;SomeModel, string&gt;&gt;

【问题讨论】:

  • 出于某种原因你想避免显式类型吗?如果是因为您想为不共享任何接口类型的不同模型重用它,您可能希望使用动态。但我不太确定它是否会起作用
  • 我已经尝试过动态但不起作用。
  • 这里确实需要该类型,否则你希望如何使用返回的表达式?
  • @DavidG 这正是您遇到的问题。不确定这是一个好方法,但这是一个有趣的学习练习。
  • @TheSoftwareJedi 关键是它几乎肯定不是一个好方法。您已经发现您现在有一个弱类型的表达式(即 LamdaExpression 而不是 Expression&lt;Func&lt;SomeModel, string&gt;)。

标签: c# linq lambda expression


【解决方案1】:

您实际上可以这样做,但类型变得未知。从这个方法返回的对象将是正确的类型Expression&lt;Func&lt;Test, string&gt;&gt;,但在编译时不能是强类型

    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; }
}

免责声明:如果你真的想在生产环境中使用它,我会清理代码很多,只得到一次反射类型,等等……

【讨论】:

  • 谢谢!你真的是绝地武士。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多