【问题标题】:lambda Expression as a propertylambda 表达式作为属性
【发布时间】: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 并获取属性值。我不知道从哪里开始,也不知道拥有这样一个可评估的属性会是什么样的语法。我是函数委托和表达式树的新手,我什至不知道要搜索的正确关键字。希望我的描述清楚;如果没有,请告诉我,必要时我会详细说明。 任何帮助将不胜感激。

【问题讨论】:

    标签: c# lambda expression


    【解决方案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&lt;Person, string&gt; 是您所拥有的代表的简写,而有人没有意识到这一点并给了您一票否决。
        • @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
        

        【讨论】:

        • 可能是第一行的命令(而不是请求)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-28
        • 2023-03-10
        • 1970-01-01
        相关资源
        最近更新 更多