【问题标题】:Retrieving nested PropertyInfo via expressions通过表达式检索嵌套的 PropertyInfo
【发布时间】:2017-11-12 02:57:49
【问题描述】:

我正在尝试创建一个函数,我可以在其中传递一个表达式来说明我感兴趣的属性。我让它适用于顶级属性,但不适用于嵌套属性。

示例模型

public class Foo {
    public string Name { get; set; } 
    public List<Foo> List { get; set; }
}

目前为止我所拥有的

    private PropertyInfo GetPropertyInfo<TModel>(Expression<Func<TModel, object>> selector)
    {
        if (selector.NodeType != ExpressionType.Lambda)
        {
            throw new ArgumentException("Selector must be lambda expression", nameof(selector));
        }

        var lambda = (LambdaExpression)selector;

        var memberExpression = ExtractMemberExpression(lambda.Body);
        if (memberExpression == null)
            throw new ArgumentException("Selector must be member access expression", nameof(selector));

        if (memberExpression.Member.DeclaringType == null)
        {
            throw new InvalidOperationException("Property does not have declaring type");
        }

        return memberExpression.Member.DeclaringType.GetProperty(memberExpression.Member.Name);
    }

    private static MemberExpression ExtractMemberExpression(Expression expression)
    {
        if (expression.NodeType == ExpressionType.MemberAccess)
        {
            return ((MemberExpression)expression);
        }

        if (expression.NodeType == ExpressionType.Convert)
        {
            var operand = ((UnaryExpression)expression).Operand;
            return ExtractMemberExpression(operand);
        }

        return null;
    }

所以:

GetPropertyInfo<Foo>(x => x.Name); // works
GetPropertyInfo<Foo>(x => x.List.Select(y => y.Name); <-- how do I get this?

我正在寻找一种从复杂对象中选择任何属性的方法。

【问题讨论】:

    标签: c# lambda expression


    【解决方案1】:

    您需要稍微扩展您的 ExtractMemberExpression 以接受 Select 调用表达式:

    private MemberExpression ExtractMemberExpression(Expression expression) {
        if (expression.NodeType == ExpressionType.MemberAccess) {
            return ((MemberExpression) expression);
        }
    
        if (expression.NodeType == ExpressionType.Convert) {
            var operand = ((UnaryExpression) expression).Operand;
            return ExtractMemberExpression(operand);
        }
        if (expression.NodeType == ExpressionType.Lambda) {            
            return ExtractMemberExpression(((LambdaExpression) expression).Body);
        }
    
        if (expression.NodeType == ExpressionType.Call) {
            var call = (MethodCallExpression) expression;
            // any method named Select with 2 parameters will do
            if (call.Method.Name == "Select" && call.Arguments.Count == 2) {
                return ExtractMemberExpression(call.Arguments[1]);
            }
        }
    
        return null;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 2016-10-21
      相关资源
      最近更新 更多