当前位置 : 主页 > 手机开发 > 其它 >

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

来源:互联网 收集:自由互联 发布时间:2021-06-19
关注这篇文章: link text我正在尝试创建一个引用属性属性的表达式树.我的代码看起来像这样: public interface IFoo{ void X {get;set;}}public interface IBar : IFoo{ void Y {get;set;}}public interface IFooBarC
关注这篇文章: 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: Instance
property ‘X’ is not defined for type
‘IBar’

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

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

您尝试访问的属性不是IBar.X,它是IFoo.X. Expression.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)));
}
网友评论