代码之家  ›  专栏  ›  技术社区  ›  Adam Driscoll

具有属性继承的表达式树导致参数异常

  •  4
  • Adam Driscoll  · 技术社区  · 14 年前

    以下为帖子: 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:实例 '国际银行账户'

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

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

    1 回复  |  直到 7 年前
        1
  •  8
  •   Jaider    6 年前

    IBar.X IFoo.X Expression.Property 方法需要声明属性的实际类型,而不是子类型。如果你不相信,试试看:

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

    IBar 是一个接口;这对一个班级来说是有效的)

    我认为最简单的方法是创建一个helper方法来解析实际的属性,方法是递归地遍历类型层次结构:

    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)));
    }