Как Func ‹DomainObject, object› возвращает имя объекта в виде строки

У меня есть такой статический метод:

    public static string MyMethod(Func<Student, object> func)
    {            
        return ??? ;
    }

и я использую его следующим образом:

    var s1 = MyMethod(student => student.ID); // Return "ID" ???
    var s2 = MyMethod(student => student.Age); // Return "Age" ???
    var s3 = MyMethod(student => student.Name); // Return "Name" ???

Как написать метод, возвращающий следующие результаты?

  • s1 : "ID"
  • s2: "Возраст"
  • s3: "Имя"

* возвращать имя каждого свойства после => в виде строки


person R R    schedule 12.12.2013    source источник
comment
Нельзя с этой подписью - это должно быть что-то вроде Expression<Func<Student, object>>.   -  person Jon    schedule 13.12.2013


Ответы (3)


Вы можете изменить подпись своего метода из

  public static string MyMethod(Func<Student, object> func)

измените это на

  public static string MyMethod(Expression<Func<Student, object>> func) {
     return GetMemeberName(func)
  } 

  public static string GetMemberName(Expression expression)
    {            
        if (expression is LambdaExpression)
        {
            var lambdaExpression = (LambdaExpression)expression;
            return GetMemberName(lambdaExpression.Body);                              
        }

        if (expression is MemberExpression)
        {
            var memberExpression = (MemberExpression)expression;
            if (memberExpression.Expression.NodeType == ExpressionType.MemberAccess)
            {
                return GetMemberName(memberExpression.Expression)+ "."+ memberExpression.Member.Name;
            }
            return memberExpression.Member.Name;
        }

        if (expression is UnaryExpression)
        {
            var unaryExpression = (UnaryExpression)expression;
           if (unaryExpression.NodeType != ExpressionType.Convert)
                throw new Exception(string.Format(
                    "Cannot interpret member from {0}",
                    expression));
            return GetMemberName(unaryExpression.Operand);
        }
        throw new Exception(string.Format("Could not determine member from {0}",expression));
    }  
person vittore    schedule 12.12.2013
comment
Это хорошо, но вы должны сказать ему, как заставить это работать. OP имеет Func<>, а не Expression. - person Gabe; 13.12.2013
comment
По сути, это набор кода, который, хотя и полезен, нигде не дает ответа на поставленный вопрос. Я бы поддержал это, если бы это был реальный ответ. - person Jon; 13.12.2013
comment
Также обратите внимание, что с параметром типа Expression вы не можете вызвать его с помощью лямбда. - person Servy; 13.12.2013
comment
@Gabe добавил некоторые пояснения - person vittore; 13.12.2013
comment
@Jon добавил некоторые детали - person vittore; 13.12.2013
comment
Зачем сбрасывать его на Expression только для того, чтобы вы могли снова вернуть его на LambdaExpression. - person Servy; 13.12.2013
comment
@Servy, чтобы один метод принимал любой тип выражения в качестве аргумента. Это могла быть группа методов. - person vittore; 13.12.2013
comment
Вы уверены в предложении MemberAccess? В частности, каков будет тип первого рекурсивного вспомогательного вызова и почему. соединение двух рекурсивных подвызовов? - person Wiktor Zychla; 13.12.2013
comment
@WiktorZychla Я написал этот код несколько лет назад, позвольте мне проверить. - person vittore; 13.12.2013
comment
@WiktorZychla, это должно работать в случае a=>a.p1.p2 и возвращать p1.p2 - person vittore; 13.12.2013
comment
Не могу проверить сейчас, но все же я единственный, кто за вас проголосовал;) - person Wiktor Zychla; 13.12.2013
comment
@WiktorZychla есть 2 взлета и 1 падение: D - person vittore; 13.12.2013

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

Эта версия, вероятно, самая короткая, она не включает рекурсию, а работает только для простых лямбда-выражений доступа к свойствам.

public static string MyFunc( Expression<Func<Student, object>> Property )
{
     if ( Property != null && Property.Body != null )
         if ( Property.Body.NodeType == ExpressionType.MemberAccess )
         {
             MemberExpression memberExpression = 
                (MemberExpression)Property.Body;

             if ( !string.IsNullOrEmpty( memberExpression.Member.Name ) )
                 return memberExpression.Member.Name;

         }

     return string.Empty;
 }
person Wiktor Zychla    schedule 12.12.2013

Из другого вопроса SO, это может быть то, что вы ищете :

public static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
{
    return (propertyExpression.Body as MemberExpression).Member.Name;
}

Чтобы использовать это, вы должны написать что-то вроде этого:

var propertyName = GetPropertyName(
    () => myObject.AProperty); // returns "AProperty"
person Aaron Palmer    schedule 12.12.2013