Свойство, к которому вы пытаетесь получить доступ, - , а не IBar.X
, это IFoo.X
. Метод Expression.Property
ожидает фактический тип, который объявляет свойство, а не подтип. Если вы не уверены, попробуйте это:
var prop = typeof(IBar).GetProperty("X");
Возвращает ноль (только потому, что 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)));
}