C#表达式树调用基类属性get方法

时间:2014-01-13 16:39:22

标签: c# reflection .net-4.5 expression-trees

我已经构建了一个表达式树,它从类派生参数并调用它们来设置另一个类中的值。它适用于大多数类型,但在派生类型上失败。如果我有:

public class A
{
    public string MyString {get; set;}
}

public class B : A
{

}

如果我使用此表达式树代码(其中value是派生实例):

// Get the type of the object for caching and ExpressionTree purposes
var objectType = value.GetType();
// Define input parameter
var inputObject = Expression.Parameter( typeof( object ), "value" );

var properties = objectType.GetProperties( BindingFlags.Instance | BindingFlags.Public );
foreach (var property in properties)
{
    Expression.Property( Expression.ConvertChecked( inputObject, property.DeclaringType ), property.GetGetMethod() )
}

我会收到这个例外:

{System.ArgumentException: The method 'My.Namespace.A.get_MyString' is not a property accessor
at System.Linq.Expressions.Expression.GetProperty(MethodInfo mi)...

我在这里做错了什么?

1 个答案:

答案 0 :(得分:5)

您需要使用属性本身而不是Getter方法:

foreach (var property in properties)
{
    Expression.Property( 
         Expression.ConvertChecked( inputObject, property.DeclaringType ),
         property);
}

基本上您需要使用此Property method代替此重载的Property method

<强>更新

对于GetGetMethod方法 - 如果var objectType等于A类型,那么它可以正常工作。如果它等于B类型,则它不起作用。

我猜,问题发生在property.DeclaringType。对于这两种情况,它都是A类型,作为其中声明的属性。但是此代码将为同一属性返回不同的ReflectedType

var reflectingTypeForA = typeof(A).GetProperty("MyString").GetGetMethod().ReflectedType;
var reflectingTypeForB = typeof(B).GetProperty("MyString").GetGetMethod().ReflectedType;

对于A,它会返回A,对于B类型,它会返回B。我的猜测是,对于B情况,Expression.Property逻辑检查property.DeclaringTypeA,但GetGetMethod的ReflectedType等于B,所以它认为它是private static PropertyInfo GetProperty(MethodInfo mi) { Type type = mi.DeclaringType; BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic; flags |= (mi.IsStatic) ? BindingFlags.Static : BindingFlags.Instance; PropertyInfo[] props = type.GetProperties(flags); foreach (PropertyInfo pi in props) { if (pi.CanRead && CheckMethod(mi, pi.GetGetMethod(true))) { return pi; } if (pi.CanWrite && CheckMethod(mi, pi.GetSetMethod(true))) { return pi; } } throw new SomeException(); } private static bool CheckMethod(MethodInfo method, MethodInfo propertyMethod) { if (method == propertyMethod) { return true; } // If the type is an interface then the handle for the method got by the compiler will not be the // same as that returned by reflection. // Check for this condition and try and get the method from reflection. Type type = method.DeclaringType; if (type.IsInterface && method.Name == propertyMethod.Name && type.GetMethod(method.Name) == propertyMethod) { return true; } return false; } 另一个物体的财产。我没有任何证明,但只有这两个成员在两个GetGetMethod调用之间是不同的

<强> UPDATE2

这是Expression.Property(MethodInfo方法)使用的代码:

if (method == propertyMethod) {
    return true; 
} 

问题出在这一行:

A

当您从类型B通过GetGetMethod获取MethodInfo时,它与类型var propertyAGetter = typeof(A).GetProperty("MyString").GetGetMethod(); var propertyBGetter = typeof(B).GetProperty("MyString").GetGetMethod(); bool areTheSame = propertyAGetter == propertyBGetter; // it equals to false 中的MethodInfo不同,并且此检查返回false。 这样的例子也返回false:

{{1}}