Expression tree with property inheritance throws an argument exception

After this post: link text I'm trying to create an expression tree that references a property of a property. My code is as follows:

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 get an exception:

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

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

If I reference IBar.Y , the method does not interrupt.

+4
source share
1 answer

The property you are trying to access is not IBar.X , it IFoo.X The Expression.Property method expects an actual type that declares a property, not a subtype. If you are not sure, try the following:

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

It returns null (just because IBar is an interface, it will work for a class)

I think the easiest way to make it work is to create a helper method to resolve the actual property, returning 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; } 

Then you can rewrite PropertyOfProperty as follows:

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

Source: https://habr.com/ru/post/1304817/


All Articles