C#中将属性名称转换为Lambda表达式

12

如何在C#中将属性名称转换为Lambda表达式?

例如:将 string prop = "Name"; 转换为 (p => p.Name)

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

谢谢!


一个 lambda 表达式不是一种类型。你是指委托还是表达式树?而且是 确切地 哪种类型? - Lucas Trzesniewski
我不明白你的问题... 你想将一个变量声明转换为属性访问表达式吗? - Matías Fidemraizer
请解释您想要实现什么。将属性名称转换为Lambda并没有真正意义。添加一些上下文。 - Pierre-Luc Pineault
在一个函数中,我有一个 Expression<Func<T, object>> param 参数,但我仅有属性名称,因此我需要将属性名称“转换”为表达式。 - Renan Araújo
2个回答

26
使用表达式树,你可以生成Lambda表达式。
using System.Linq.Expressions;
public static Expression<Func<T, object>> GetPropertySelector<T>(string propertyName)
{
    var arg = Expression.Parameter(typeof(T), "x");
    var property = Expression.Property(arg, propertyName);
    //return the property as object
    var conv = Expression.Convert(property, typeof(object));
    var exp = Expression.Lambda<Func<T, object>>(conv, new ParameterExpression[] { arg });
    return exp;
}

对于 Person,你可以这样调用:

var exp = GetPropertySelector<Person>("Name");//exp: x=>x.Name

1
这不是反射。 - Matías Fidemraizer
这仅适用于字符串。有没有办法使Expression.Lambda<Func<Person,string>>通用?我尝试过Expression.Lambda<Func<Person,object>>但不起作用。 - Renan Araújo
我已经修改它以支持泛型。 - Taher Rahgooy
我会说:“你可以使用表达式树” :D - Matías Fidemraizer
表达式树的某些部分实际上是基于反射的。看起来 conv 在这里是多余的,你可以直接在 Expression.Lambda 中传递 property 而不是 conv(经过测试,这种方式可行)。 - Hopeless
2
@Hopeless:对于值类型,如int,需要进行转换。如果没有转换,将会抛出以下异常:“无法将类型为'System.Int32'的表达式用于返回类型'System.Object'”。 - Kamarey

1
一个 lambda 只是一个匿名函数。您可以像常规方法一样将 lambda 存储在委托中。我建议您尝试将“Name”设置为属性。 public string Name { get { return p.Name; } } 如果您真的想要一个 lambda,请使用 Func 等委托类型。 public Func<string> Name = () => p.Name;

好的,是的,因为它没有名称来定义其位置。 - Philippe Paré
那么表达式树呢?它们也是委托吗?:P - Matías Fidemraizer
公平地说,我不熟悉表达式树(如果你在谈论Linq的Expression类),但我认为它既不继承自Delegate也不是委托类型。 - Philippe Paré
他们不是委托。他们可以编译成委托。 - Matías Fidemraizer
让我们在聊天中继续这个讨论 - Philippe Paré

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