reflection在抽象类的属性上找不到私有的setter

当我在抽象类中有这个属性时:

public IList Components { get; private set; } 

然后当我打电话:

 p.GetSetMethod(true) 

如果p是一个指向我的属性的PropertyInfo对象,我得到null。

但是,如果我将属性setter更改为protected,我可以通过reflection看到它。 为什么是这样? 我似乎没有回忆起非抽象类的这个问题……

我假设您在抽象类的派生类型的对象上调用它。 该课程根本没有属性设定者。 它只位于您的抽象基础上。 这就是为什么它在您将其标记为protected 。 获取属性设置器时,需要使用抽象类’ Type

这是一个老线程,但我最近遇到了类似的问题,以上都没有为我工作。 添加我的解决方案,因为它可能对其他人有用。

如前所述,如果属性的setter是私有的,则它在inheritance的类中不存在。 对我来说DeclaringType的是使用PropertyInfo DeclaringType降低一级

因此,使用setter检索属性的代码如下所示:

 var propertyInfo = typeof(MyClass) .GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance) .DeclaringType .GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance); 

在这种情况下, propertyInfo包含SetMethod的值,因此您可以使用reflection设置值。

C#Interactive窗口中的一些简短实验表明,对于在A类上声明的属性P ,以下工作正常:

 var p = typeof(A).GetProperty("P").GetSetMethod(true) 

但是只要你用A的子类尝试相同的东西, GetSetMethod就不再解析私有set访问器:

 // class B : A {} var p = typeof(B).GetProperty("P").GetSetMethod(true) // produces 'null'. 

换句话说,当reflection类型与属性的声明类型相同时,您试图显然只适用于private访问器。

诀窍是使用BindingFlags枚举来指定在获取PropertyInfo对象时希望包含私有成员:

 PropertyInfo p = obj.GetType().GetProperty("Components", BindingFlags.NonPublic | BindingFlags.Instance); 

建立@piotrwolkowski的工作

 var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var propertyInfo = typeof(MyClass).GetProperty("Components", flags); // only go to the declaring type if you need to if (!propertyInfo.CanWrite) propertyInfo = propertyInfo.DeclaringType.GetProperty("Components", flags); 

我将公共和非公共添加到我的用例的绑定标志(它可能是矫枉过正的,我没有时间进一步追求它)

我正在设置一个对象的实例,该对象inheritance自具有公共get和private set的抽象基础

再一次,归功于@piotrwolkowski

以下实验为我揭开了这个问题。 请注意,基类不必是abstract来重现问题。

 public class Base { public string Something { get; private set; } } public class Derived : Base { } public class MiscTest { static void Main( string[] args ) { var property1 = typeof( Derived ).GetProperty( "Something" ); var setter1 = property1.SetMethod; //null var property2 = typeof( Base ).GetProperty( "Something" ); var setter2 = property2.SetMethod; //non-null bool test1 = property1 == property2; //false bool test2 = property1.DeclaringType == property2.DeclaringType; //true var solution = property1.DeclaringType.GetProperty( property1.Name ); var setter3 = solution.SetMethod; //non-null bool test3 = solution == property1; //false bool test4 = solution == property2; //true bool test5 = setter3 == setter2; //true } } 

我从中学到的并且发现令人惊讶的是,派生类型上的PropertyInfo是与基类型上的PropertyInfo不同的实例。 奇怪的!