.net определить функцию, которая принимает лямбда-выражение - PullRequest
3 голосов
/ 10 декабря 2010

Я хочу определить функцию, подобную функции шаблона расширения MVC TextBoxFor

Интересно, что для этой функции мне не нужно указывать тип TProperty. Как я могу установить это в своем определении функции.

Мой код выглядит так:

public class Helper<TItem>
{
    public string GetMemberName(Expression<Func<TItem, TProperty>> expression)
    {
        ... returns TProperty.Name

    }
}

Фактическая проблема заключается в том, что он не компилируется ... потому что не может найти тип TProperty.

В результате я хочу определить класс один раз с типом ... и затем использовать функцию GetMemberName, чтобы получить имя каждого члена, как в MVC framework.

Helper<Employee> h = new Helper<Employee>();
string name = h.GetMemberName(e=>e.Name);
....

Я не хочу указывать тип TProperty при написании кода. В основном это может быть любой объект.

Спасибо

Radu

Ответы [ 4 ]

3 голосов
/ 10 декабря 2010

Это то, что вам нужно:

public class Helper<TItem>
{
    public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression)
    {
        return string.Empty; // I didn't implement it
    }
}

Просто добавьте <TProperty> к имени вашего метода, чтобы сделать его общим. И тип TProperty может быть выведен из предоставленного выражения, поэтому вам не нужно указывать его тип при использовании, это может быть просто:

Helper<Employee> h = new Helper<Employee>();
h.GetMemberName( e=>e.Name); //if Employee has such a property
1 голос
/ 10 декабря 2010

Следующая функция возвращает имя любого свойства, переданное ему с помощью лямбда-выражения:

    public static string Property<T>(Expression<Func<T>> e)
    {
        var member = (MemberExpression)e.Body;
        return member.Member.Name;
    }
0 голосов
/ 10 декабря 2010

Я написал эту функцию один раз, но точно не помню.Но сначала измените подпись делегата на это Func<T, object>, затем для простых типов данных получите тело выражения и приведите его к MemberExpression и получите имя первого параметра

, если доступный членсложный, вы должны привести тело выражения к UnaryExpression , взять первый параметр и привести его к MemberExpression и сделать то, что вы делали на первом шаге.

Игра сQuickWatch при отладке функции может привести вас к решению.Стоит отметить, что чтение HtmlHelper в MVC-коде может быть полезным.

РЕДАКТИРОВАТЬ: Грубо запомнилось

Лучше всего написать эту функцию как метод расширения (с ограничениемна тип, где это применимо, если хотите), так что предоставление типа Employee также больше не требуется, потому что это выводится из использования.

Итак, ваша функция такова:

public static class Helper
{
    public static string Item<TItem,TMember>(this TItem obj, Expression<Func<TItem, TMember>> expression)
    {
        if (expression.Body is MemberExpression)
        {
            return ((MemberExpression)(expression.Body)).Member.Name;
        }
        if(expression.Body is UnaryExpression)
        {
            return ((MemberExpression)((UnaryExpression)(expression.Body)).Operand).Member.Name;
        }
        throw new InvalidOperationException();
    }
}

Так что ваш код будет намного чище

Employee emp = new Employee();
emp.Item(o=>o.Name);

Надеюсь, вам поможет

0 голосов
/ 10 декабря 2010

Вы можете использовать класс ModelMetaData для извлечения информации из Expression.

public string GetMemberName<TProperty>(Expression<Func<TItem, TProperty>> expression) {
   var meta = ModelMetaData.FromLambdaExpression(expression, null);
   return meta.PropertyName; // Or something else
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...