лямбда-выражение как свойство - PullRequest
9 голосов
/ 23 сентября 2011

У меня есть рабочая установка, которая не сильно напечатана и зависит от отражения.

У меня есть класс, скажем

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 на объекте person и получите значение свойства. Я понятия не имею, с чего начать и как будет выглядеть синтаксис, чтобы иметь такое свойство, которое можно оценить. Я новичок в функции делегатов и деревьев выражений, которые даже не знаю подходящих ключевых слов для поиска. Надеюсь, мое описание понятно; если нет, дайте мне знать, и я сообщу подробности по мере необходимости. Любая помощь будет высоко ценится.

Ответы [ 4 ]

2 голосов
/ 23 сентября 2011

Используйте делегата:

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

Тогда ваш лямбда-вход будет работать ...

1 голос
/ 23 сентября 2011

Вы можете попробовать что-то подобное, чтобы не кодировать имена свойств в виде строк, если это то, что вы подразумеваете, говоря строго типизированный :

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);
    }
}
0 голосов
/ 23 сентября 2011

Я думаю, что делегат - это то, что вам нужно. Примерно так:

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
                   });
0 голосов
/ 23 сентября 2011

(Ваш вопрос ясный, но длинный. Обрежьте начальный материал.)

Вот так ASP.NET MVC использует отражения и лямбда-выражения для создания имен полей на входах 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
...