关注这篇文章: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
是一个接口(interface);它适用于一个类)我认为使其工作的最简单方法是创建一个辅助方法来解析实际属性,方法是递归地向上走类型层次结构:
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)));
}
关于.net - 具有属性继承的表达式树导致参数异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2496256/