简体   繁体   中英

Reflection can't find private setter on property of abstract class

When I have this property in an abstract class:

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

Then when I call:

p.GetSetMethod(true)

with p being a PropertyInfo object pointing to my property, I get null.

However if I change the property setter to protected, I can see it via reflection. Why is this? I don't seem to recall having this problem with non-abstract classes...

I assume you are calling this on an object from a derived type of your abstract class. There isn't a property setter at all on that class. It is only located on your abstract base. This is why it works when you mark it as protected . You need use your abstract class' Type instead when getting the property setter.

It's an old thread but I run into similar issue recently and none of the above worked for me. Adding my solution as it may be useful for others.

As said before if the setter of a property is private it does not exist in the inherited class. What worked for me was to go one level lower using DeclaringType of the PropertyInfo

So the code to retrieve the property with the setter would look like this:

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

In this case the propertyInfo contains a value for SetMethod so you can set the value using reflection.

Some brief experimentation in the C# Interactive window suggests that for a property P declared on a class A , the following works just fine:

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

But as soon as you attempt the same thing with a subclass of A , GetSetMethod no longer resolves the private set accessor:

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

In other words, what you attempted apparently only works for private accessors when the reflected type is the same as the property's declaring type.

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

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

To build on the work of @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);

I added both public and non-public to the binding flags for my use case (it may be overkill and I don't have the time to pursue it further)

I was setting the instance of an object that inherited from an abstract base with public get and private set

Again, all credit to @piotrwolkowski

The following experimentation uncovered the issue for me. Note that the base class doesn't have to be abstract to reproduce the problem.

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
    }
}

What I learned from this and found surprising, is that the PropertyInfo on the derived type is a different instance than the PropertyInfo on the base type. Weird!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM