【问题标题】:Expression Tree with Property Inheritance causes an argument exception具有属性继承的表达式树导致参数异常
【发布时间】:2010-03-22 22:35:26
【问题描述】:

在这篇文章之后:link text 我正在尝试创建一个引用属性属性的表达式树。我的代码如下所示:

public interface IFoo
{
    void X {get;set;}
}

public interface IBar : IFoo
{
    void Y {get;set;}
}

public interface IFooBarContainer
{
    IBar Bar {get;set;}
}

public class Filterer
{
     //Where T = "IFooBarContainer"
     public IQueryable<T> Filter<T>(IEnumerable<T> collection)
     {
              var argument = Expression.Parameter(typeof (T), "item");

              //...

               //where propertyName = "IBar.X";
               PropertyOfProperty(argument, propertyName); 
     }

        private static MemberExpression PropertyOfProperty(Expression expr, string propertyName)
        {
            return propertyName.Split('.').Aggregate<string, MemberExpression>(null, (current, property) => Expression.Property(current ?? expr, property));
        }
}

我收到异常:

System.ArgumentException:实例 没有为类型定义属性“X” 'IBar'

ReSharper 将上面链接中的代码转换为我示例中的简明语句。两种形式的方法都返回相同的错误。

如果我引用IBar.Y,该方法不会失败。

【问题讨论】:

    标签: .net linq expression-trees


    【解决方案1】:

    您尝试访问的属性不是IBar.X,而是IFoo.XExpression.Property 方法需要声明属性的实际类型,而不是子类型。如果您不相信,请尝试:

    var prop = typeof(IBar).GetProperty("X");
    

    它返回 null(只是因为 IBar 是一个接口;它适用于一个类)

    我认为让它工作的最简单方法是创建一个帮助方法来解析实际属性,通过递归地遍历类型层次结构:

    private PropertyInfo GetProperty(Type type, string propertyName)
    {
        PropertyInfo prop = type.GetProperty(propertyName);
        if (prop == null)
        {
            var baseTypesAndInterfaces = new List<Type>();
            if (type.BaseType != null) baseTypesAndInterfaces.Add(type.BaseType);
            baseTypesAndInterfaces.AddRange(type.GetInterfaces());
            foreach(Type t in baseTypesAndInterfaces)
            {
                prop = GetProperty(t, propertyName);
                if (prop != null)
                    break;
            }
        }
        return prop;
    }
    

    然后你可以重写你的PropertyOfProperty 如下:

    private static MemberExpression PropertyOfProperty(MemberExpression expr, string propertyName)
    {
        return propertyName
                   .Split('.')
                   .Aggregate<string, MemberExpression>(
                       expr,
                       (current, property) =>
                           Expression.Property(
                               current,
                               GetProperty(current.Type, property)));
    }
    

    【讨论】:

    • Thomas,听起来不错!只是想知道重新设计的 PropertyOfProperty 方法中的“arg”是什么?
    • 是的,一个错误的复制/粘贴...刚刚修复它。我还通过传递expr 作为Aggregate 方法的种子来简化代码以摆脱?? 运算符,它应该具有相同的效果
    猜你喜欢
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2016-11-15
    • 2013-07-01
    • 2017-03-14
    相关资源
    最近更新 更多