lambda 表达式作为属性
Posted
技术标签:
【中文标题】lambda 表达式作为属性【英文标题】:lambda Expression as a property 【发布时间】:2011-11-23 13:27:21 【问题描述】:我有一个非强类型且依赖于反射的工作设置。
我有课,比如说
class Person
public string FirstName get ; set;
public string LastName get; set;
public int Age get; set;
...
// some more public properties
和
class CellInfo
public string Title get; set;
public string FormatString get; set;
我有一本这样的字典
Dictionary<string, CellInfo> fields = new Dictionary<string, CellInfo>();
fields.Add("FirstName", new CellInfo Title = "First Name", FormatString = "Foo");
fields.Add("LastName", new CellInfo Title = "Last Name", FormatString = "Bar");
这是一个简单的字典,包含属性名称和一些关于它们的信息。 我将字典传递给另一个处理 Person 实例的模块,我这样做了
Dictionary<string, CellInfo> fields = SomeMethodToGetDictionary();
foreach(Person p in someCollection)
foreach(var field in fields)
object cellValue = type(Person).GetProperty(field.Key).GetValue(p, null);
// use cellValue and info on field from field.Value somewhere.
...
这种为字段名称传递字符串并使用反射的方法有效,但我想知道是否有一种强类型的方法可以做到这一点。
我想到的是拥有一个存储 linq 表达式的属性,就像这样
fields.Add("FirstName", new CellInfo
Title = "First Name",
FormatString = "Foo",
EvalExpression = p => p.FirstName
);
在使用过程中,以某种方式在人员对象上使用EvalExpression
并获取属性值。我不知道从哪里开始,也不知道拥有这样一个可评估的属性会是什么样的语法。我是函数委托和表达式树的新手,我什至不知道要搜索的正确关键字。希望我的描述清楚;如果没有,请告诉我,必要时我会详细说明。
任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:使用委托:
class CellInfo
public string Title get; set;
public string FormatString get; set;
public Func<Person, object> EvalExpression get; set;
那么你的 lambda 输入就可以工作了……
【讨论】:
【参考方案2】:如果您说强类型化是这个意思,您可以尝试这样的方法,而不必将属性名称编码为字符串:
class CellInfo<T>
public string Title get; set;
public string FormatString get; set;
public Func<T, object> Selector get; set;
Dictionary<string, CellInfo<Person>> dict = new Dictionary<string, CellInfo<Person>>();
dict.Add("LastName", new CellInfo<Person> Selector = p => p.LastName );
dict.Add("Age", new CellInfo<Person> Selector = p => p.Age );
foreach (Person p in someCollection)
foreach (var cellInfo in dict)
object value = cellInfo.Value.Selector(p);
【讨论】:
【参考方案3】:我认为代表是您所需要的。像这样的:
public delegate string EvalExpressionDelegate (Person);
class CellInfo
public string Title get; set;
public string FormatString get; set;
public EvalExpressionDelegate EvalExpression = null;
fields.Add("FirstName", new CellInfo
Title = "First Name",
FormatString = "Foo",
EvalExpression = p => p.FirstName
);
【讨论】:
+1 好信息。我猜Func<Person, string>
是您所拥有的代表的简写,而有人没有意识到这一点并给了您一票否决。
@ProfessorChaos 我认为否决票可能是因为写出委托被认为是老式的做法,尽管它可以有其优点,例如命名参数。【参考方案4】:
(你的问题很清楚但很长。修剪最初的东西。)
这就是 ASP.NET MVC 使用反射和 lambda 表达式在 html 输入等上创建字段名称的方式。所以你可以看看源代码。
简单来说,您必须将您的表达式转换为成员表达式并获取名称。简单:
MemberExpression memberExpression = EvalExpression.Body as MemberExpression;
if (memberExpression == null)
throw new InvalidOperationException("Not a memberExpression");
if (!(memberExpression.Member is PropertyInfo))
throw new InvalidOperationException("Not a property");
return memberExpression.Member.Name; // returns FirstName
【讨论】:
可能是第一行的命令(而不是请求)。以上是关于lambda 表达式作为属性的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin函数 ⑥ ( 函数参数为 Lambda 表达式 | Lambda 表达式作为参数的简略写法 | 唯一参数的简略写法 | 最后一个参数的简略写法 )