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