Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调用基类属性get方法的C#表达式树_C#_Reflection_.net 4.5_Expression Trees - Fatal编程技术网

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

调用基类属性get方法的C#表达式树,c#,reflection,.net-4.5,expression-trees,C#,Reflection,.net 4.5,Expression Trees,我构建了一个表达式树,它从一个类中派生参数,并调用它们来设置另一个类中的值。它对大多数类型都很有效,但对派生类型无效。如果我有: public class A { public string MyString {get; set;} } 及 如果使用此表达式树代码(其中value是派生实例): 我将收到此例外: {System.ArgumentException: The method 'My.Namespace.A.get_MyString' is not a property ac

我构建了一个表达式树,它从一个类中派生参数,并调用它们来设置另一个类中的值。它对大多数类型都很有效,但对派生类型无效。如果我有:

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

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

我将收到此例外:

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

我做错了什么?

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

foreach (var property in properties)
{
    Expression.Property( 
         Expression.ConvertChecked( inputObject, property.DeclaringType ),
         property);
}
基本上你需要使用这个,而不是这个

更新

对于getMethod方法-如果
var objectType
等于
A
类型,则该方法有效。如果它等于
B
type,则它不起作用

我猜问题出在
属性.DeclaringType
中。对于这两种情况,它都是
类型,正如在其中声明的属性一样。但是对于相同的属性,此代码将返回不同的
ReflectedType

var reflectingTypeForA = typeof(A).GetProperty("MyString").GetGetMethod().ReflectedType;
var reflectingTypeForB = typeof(B).GetProperty("MyString").GetGetMethod().ReflectedType;
对于
A
它返回
A
,对于
B
类型它返回
B
。我的猜测是,对于
B
大小写表达式。属性逻辑检查
属性。DeclaringType
A
,但GetGetMethod的
ReflectedType
等于
B
,因此它认为它是另一个对象的属性。我没有任何证据证明这一点,但只有这些成员在两个getMethod调用之间是不同的

更新2

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

问题出在这一行:

if (method == propertyMethod) {
    return true; 
} 
当您通过GetGetMethod从类型
A
获取MethodInfo时,它与类型
B
中的MethodInfo不同,此检查返回false。 该示例还返回false:

var propertyAGetter = typeof(A).GetProperty("MyString").GetGetMethod();
var propertyBGetter = typeof(B).GetProperty("MyString").GetGetMethod();
bool areTheSame = propertyAGetter == propertyBGetter; // it equals to false

这成功了,谢谢!我会给你答案,如果你能告诉我为什么它有效,因为我不理解,不理解我的代码会让我痛苦!把我的猜测加入到答案中:)该死,答案很棒。谢谢@Sergey-非常感谢。我想知道这在技术上是否是.NET framework中的一个bug?从技术上讲,这两个对象是不同的,因为ReflectedType。所以,这不是一个错误。以下是Jon Skeet给出的关于ReflectedType的答案-我不同意他们关于
ReflectedType
的设计决策,但至少现在我明白了为什么我的代码会被破坏。:)
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; 
} 
if (method == propertyMethod) {
    return true; 
} 
var propertyAGetter = typeof(A).GetProperty("MyString").GetGetMethod();
var propertyBGetter = typeof(B).GetProperty("MyString").GetGetMethod();
bool areTheSame = propertyAGetter == propertyBGetter; // it equals to false