无法使用反射读取受保护的属性

时间:2019-12-09 16:21:44

标签: c# system.reflection

类定义

public abstract class MyBase
{
    protected string _foo = "Hello";

    protected string Foo
    {
        get {
            return _foo;
        }
    }
}

public class MyChild : MyBase
{
    public MyChild() {
        Console.WriteLine("Hello from MyChild: {0}", Foo);
    }
}

读取非公共属性的功能:

public static class ObjectExtensions
{
    public static T ReadProperty<T>(this object obj, string name) {
        Type tp = obj.GetType();

        // This loop is for testing purposes only.      
        foreach (var t in tp.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)) {
            Console.WriteLine("Property name: {0}: Can read: {1}", t.Name, t.CanRead);

            // OUTPUT: Property name: Foo: Can read: True
        }

        var pi = tp.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

        if (pi == null) {
            Console.WriteLine("Property not found!");
            return default(T);
        }

        if (pi.GetType() is T) {
            return (T)pi.GetValue(obj);
        }

        try {
            return (T)Convert.ChangeType(pi.GetValue(obj), typeof(T));
        } catch (InvalidCastException) {
            return default(T);
        }
    }
}

主要功能:

public class Program
{
    public static void Main()
    {
        var c = new MyChild();

        Console.WriteLine("Foo from MyChild: {0}", c.ReadProperty<string>("Foo"));
    }
}

我尝试使用其他BindingFlags,但始终会导致以下异常:

Hello from MyChild: Hello
Property name: Foo: Can read: True
Run-time exception (line 25): Attempt by method 'ObjectExtensions.ReadProperty<System.__Canon>(System.Object, System.String)' to access method 'MyBase.get_Foo()' failed.

Stack Trace:

[System.MethodAccessException: Attempt by method 'ObjectExtensions.ReadProperty<System.__Canon>(System.Object, System.String)' to access method 'MyBase.get_Foo()' failed.]
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags)
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
   at System.Reflection.PropertyInfo.GetValue(Object obj)
   at ObjectExtensions.ReadProperty[T](Object obj, String name) :line 25
   at Program.Main() :line 57

我做错了什么?

Dotnet Fiddle

0 个答案:

没有答案