【问题标题】:C# Generate Expression<Func<Foo, object>>C# 生成表达式<Func<Foo, object>>
【发布时间】:2016-10-25 19:49:25
【问题描述】:

我正在使用一个库,其中包含一个函数,该函数采用表达式参数 x => x.Name。

使用反射,我试图为 Foo 的每个属性调用它。这意味着我需要为每个属性创建一个 Expression> 类型的表达式。

我一直在阅读有关表达式树的文章,但没有任何内容涵盖这种情况。

foreach (var property in typeof(Foo).GetProperties())
{
    ParameterExpression pe = Expression.Parameter(typeof(Foo), "x");
    MemberExpression me = Expression.Property(pe, property.Name);

    Expression<Func<Foo, object>> expression = ...  // x => x.Name

    Bar(expression, property.Name);
}

已解决:

foreach (var property in typeof(Foo).GetProperties())
{
    ParameterExpression pe = Expression.Parameter(typeof(Foo), "x");
    MemberExpression me = Expression.Property(pe, property.Name);

    var expression = (Expression<Func<Foo, object>>)
                  Expression.Lambda(Expression.Convert(me, typeof(object)), pe);

    Bar(expression, property.Name);
}

【问题讨论】:

标签: c# expression


【解决方案1】:

问题是你在编译时显然不知道Foo 的类型,否则你可以简单地使用泛型Expression.Lambda 重载创建一个lambda 表达式并且没问题。 有一个重载Expression.Lambda 将创建一个LambdaExpression 并从您指定的表达式派生类型参数。这意味着,它将从参数表达式和您用作主体的成员表达式中扣除。

不过,在这两种实现中,都有一个问题。返回类型object 是一个引用类型。然而,这些属性可能会返回一个值类型(例如int),这需要强制转换。通常,编译器会为您执行此操作。在这种情况下,您必须自己执行此操作。

private IEnumerable<LambdaExpression> CreateExpressions(Type fooType)
{
    foreach (var property in fooType.GetProperties())
    {
        ParameterExpression pe = Expression.Parameter(fooType, "x");
        MemberExpression me = Expression.Property(pe, property.Name);

        yield return Expression.Lambda(Expression.Convert(me, typeef(object)), pe);
    }
}

如果您在编译时知道Foo 的类型,您可以简单地将泛型参数Func&lt;Foo, object&gt; 添加到Lambda 方法中。

【讨论】:

    猜你喜欢
    • 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
    相关资源
    最近更新 更多