Expression Tree with Property Inheritance causes an argument exception

戏子无情 提交于 2019-12-22 08:25:32

问题


Following this post: link text I'm trying to create an expression tree that references the property of a property. My code looks like this:

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

I receive the exception:

System.ArgumentException: Instance property 'X' is not defined for type 'IBar'

ReSharper turned the code in the link above into the condensed statement in my example. Both forms of the method returned the same error.

If I reference IBar.Y the method does not fail.


回答1:


The property you're trying to access is not IBar.X, it's IFoo.X. The Expression.Property method expects the actual type that declares the property, not a subtype. If you're not convinced, try that :

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

It returns null (only because IBar is an interface ; it would work for a class)

I think the easiest way to make it work is to create a helper method to resolve the actual property, by walking up the type hierarchy recursively :

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

You can then rewrite your PropertyOfProperty as follows :

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


来源:https://stackoverflow.com/questions/2496256/expression-tree-with-property-inheritance-causes-an-argument-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!