如何使用反射在运行时构建C#“表达式”?

10
到目前为止,我还没有找到一篇关于表达式的好文章——以及如何查看C# lambda语句并说“哦,那是一个blah blah”的文章……所以,如果你知道一篇好的文章,我也会把它作为答案感激不尽。
代码示例来解释问题
因此......给定以下c#代码:
public class SomeClass<T>
{
    public TResult SomeMethod<TResult>(Expression<Func<T, TResult>> expression)
    {
        // This is just an example... don't get hung up on this :)
        return default(TResult);
    }
}

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }
}

我该如何做这件事...

var blah = new SomeClass<Person>();

blah.SomeMethod(p => p.FirstName);

在运行时(使用反射)?

我期望得到的回答

我有点期望得到这样的回答...但我确定我的表达方式可能有些偏差。

// By the way, these values are being passed to me... so you
// can't change this part of the question :)
Type personType = typeof(Person);
string propertyName = "FirstName";

// THIS CODE BELOW IS OBVIOUSLY WRONG, BUT YOU GET THE IDEA OF
// WHAT I HOPE TO DO... THIS LINE OF CODE BELOW IS **ALL** I'M
// ASKING HOW TO DO :)
var expression = Expression.MakeUnary(ExpressionType.Lambda,
    Expression.Property(Expression.Parameter(personType, "p"),
    propertyName), typeof(string));

blah.SomeMethod(expression);
2个回答

6

试试这个:

var functorParam = Expression.Parameter(typeof(Person));
var lambda = Expression.Lambda(
    Expression.Property(functorParam, typeof(Person).GetProperty("FirstName"))
,   functorParam /* <<= EDIT #1 */
);
blah.SomeMethod((Expression<Func<Person,string>>)lambda); /* EDIT #2 */

blah.SomeMethod(f); 无法编译......但我感觉这非常接近。 - Timothy Khouri
如果我理解你的意图正确的话,SomeMethod 应该使用 Func<T, TResult> functor 而不是 Expression<Func<T, TResult>> expression 作为参数。这样你就可以像这样写:var personsProp = functor(myPerson); 并获取到姓氏了。 - Sergey Kalinichenko
我调用的方法不能更改...它是我引用的程序集的一部分,因此我没有更改它的选项...这就是为什么我在问这个问题 :) - Timothy Khouri
@TimothyKhouri 移除 lambda.Compile 并直接传递 lambda。 - Sergey Kalinichenko

1

ExpressionBuilder 是最好的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接