反射无法在抽象类的属性上找到私有的setter

时间:2013-12-24 16:12:21

标签: c# .net reflection

当我在抽象类中拥有此属性时:

public IList<Component> Components { get; private set; }

然后我打电话:

p.GetSetMethod(true)

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

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

6 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:6)

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

如前所述,如果属性的setter是private,则它不存在于继承的类中。对我有用的是使用DeclaringType

PropertyInfo降低一级

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

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

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

答案 2 :(得分:3)

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

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

但是只要您使用A的子类尝试相同的操作,GetSetMethod就不再解析私有set访问者:

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

换句话说,当反射类型与属性的声明类型相同时,您尝试的只显示private个访问器。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

以@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);

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

我正在设置一个从具有公共get和private set

的抽象基础继承的对象的实例

再一次,归功于@piotrwolkowski

答案 5 :(得分:0)

以下实验为我揭开了这个问题。请注意,基类不必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不同。怪异!