Получить MemberInfo дочернего свойства из выражения MemberExpression

Я пытаюсь получить MemberInfo для дочернего свойства из MemberExpression. Я нашел способы получить полное имя вложенного типа, но не получить весь MemberInfo вложенного типа. Вот быстрый пример сценария, о котором я говорю:

Некоторые простые модели (цель состоит в том, чтобы в конечном итоге получить MemberInfo свойства Data класса Child)

public class Parent
{
    public int ParentProperty { get; set; }
    public Child Child { get; set; }
}

public class Child
{
    public string Data { get; set; }
}

Лямбда-выражение

Expression<Func<Parent,string>> func = new Func<Parent, string>(p =>
{
    return p.Child.Data;
});

Код, используемый для получения MemberInfo из лямбда-выражения.

internal static MemberInfo FindMemberInfoFromLambda(LambdaExpression lambda)
    {
        var expression = (Expression) lambda;
        var flag = false;

        while (!flag)
        {
            switch (expression.NodeType)
            {
                case ExpressionType.Convert:
                    expression = ((UnaryExpression) expression).Operand;
                    continue;
                case ExpressionType.Lambda:
                    expression = ((LambdaExpression) expression).Body;
                    continue;
                case ExpressionType.MemberAccess:
                    var memberExpression = (MemberExpression) expression;
                    if (memberExpression.Expression.NodeType == ExpressionType.Parameter ||
                        memberExpression.Expression.NodeType == ExpressionType.Convert)
                        return memberExpression.Member;
                    throw new Exception();
                default:
                    flag = true;
                    continue;
            }
        }
        throw new Exception();
    }

Этот код прекрасно работает, если я пытаюсь получить ParentProperty класса Parent, но когда я пытаюсь получить MemberInfo свойства Data класса Child, он не работает. Я видел несколько вопросов Stackru, опубликованных при получении полного имени дочернего свойства, но ничего при получении полного MemberInfo этого. Кто-нибудь делал это раньше или может помочь мне в правильном направлении?

2 ответа

Выражение, которое вы получаете - MemberExpression, вы можете получить его свойство Member напрямую:

class Program
{
    class Parent
    {
        public int A { get; set; }
        public Child Child { get; set; }
    }

    class Child
    {
        public string Data { get; set; }
    }

    public static MemberInfo GetMemberInfo(LambdaExpression exp)
    {
        var body = exp.Body as MemberExpression;
        return body.Member;
    }

    static void Main(string[] args)
    {
        Expression<Func<Parent, string>> func1 = p => p.Child.Data;
        Console.WriteLine(GetMemberInfo(func1));
        Expression<Func<Parent, int>> func2 = p => p.A;
        Console.WriteLine(GetMemberInfo(func2));
    }
}

Выход:

System.String Data
Int32 A

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

В своем коде в разделе MemberAccess вы проверяете, принадлежит ли элемент параметру, в данном случае Parent. Если вы удалите эту проверку, вы получите член для данных

Изменить этот раздел

case ExpressionType.MemberAccess:
    var memberExpression = (MemberExpression) expression;
    if (memberExpression.Expression.NodeType == ExpressionType.Parameter ||
        memberExpression.Expression.NodeType == ExpressionType.Convert)
        return memberExpression.Member;
    throw new Exception();

к

case ExpressionType.MemberAccess:
    var memberExpression = (MemberExpression) expression;
    return memberExpression.Member;

Я не знаю, почему у вас была защита для параметра, если он вам нужен в определенных случаях, вы можете создать другой метод или передать параметр.

Другие вопросы по тегам