lambda Expression作为属性

时间:2011-09-23 10:21:16

标签: c# lambda expression

我有一个工作设置,它没有强类型,依赖于反射。

我有一节课,说

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

这是一个简单的字典,其中包含属性Names和一些有关它们的信息。 我将字典传递给处理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
                   });

在使用过程中,以某种方式在person对象上使用EvalExpression并获取属性值。我不知道从哪里开始或者有什么语法可以像这样具有可评估的属性。我是新手,我甚至不知道要搜索的正确关键字的代理和表达式树。希望我的描述清楚;如果没有,请告诉我,我会在必要时详细说明。 任何帮助都会非常感激。

4 个答案:

答案 0 :(得分:2)

使用代理:

class CellInfo {
    public string Title {get; set; }
    public string FormatString {get; set; }
    public Func<Person, object> EvalExpression { get; set; }
}

然后你的lambda输入将起作用......

答案 1 :(得分:1)

你可以尝试这样的事情,不必将属性名称编码为字符串,如果你的意思是强类型

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

答案 2 :(得分:0)

我认为代表就是你需要的。像这样:

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

答案 3 :(得分:-1)

(你的问题很清楚但很长。修剪最初的东西。)

这就是ASP.NET MVC使用反射和lambda表达式在HTML输入上创建字段名称等的方式。所以你可以查看一下这个问题的源代码。

简单来说,您必须将表达式转换为Member表达式并获取名称。易:

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