使用反射获取私有属性的私有属性

20
public class Foo
{
    private Bar FooBar {get;set;}

    private class Bar
    {
        private string Str {get;set;}
        public Bar() {Str = "some value";}
    }
 }

如果我有类似上面的东西并且我有一个Foo的引用,我如何使用反射从Foo的FooBar中获取值Str?我知道实际上没有什么理由去做这样的事情(或者只有极少数的方式),但是我认为一定有方法可以做到,但我想不出如何完成。


1
你尝试了什么?稍微谷歌一下,再试错几次,你很快就能完成这个任务。 - Charles Mager
可能是访问私有字段的重复问题。 - Emz
1
这并不是一件难事,它与公共的方法并没有太大的区别,你只需要指定不同的“BindingFlags”即可。 - Ron Beyer
我的问题与此处找到的每个示例都不同,因为它只深入了一层。我在问题正文中输入了错误的问题,与标题中正确提出的问题不同。 - claudekennilol
2个回答

37
你可以使用 GetProperty 方法,以及 NonPublicInstance 绑定标志。
假设你有一个实例 f,属于 Foo 类:
PropertyInfo prop =
    typeof(Foo).GetProperty("FooBar", BindingFlags.NonPublic | BindingFlags.Instance);

MethodInfo getter = prop.GetGetMethod(nonPublic: true);
object bar = getter.Invoke(f, null);

更新:

如果你想要访问Str属性,只需要在获取到的bar对象上执行相同的操作即可:

PropertyInfo strProperty = 
    bar.GetType().GetProperty("Str", BindingFlags.NonPublic | BindingFlags.Instance);

MethodInfo strGetter = strProperty.GetGetMethod(nonPublic: true);

string val = (string)strGetter.Invoke(bar, null);

1
我在问题正文中说错了话,并打出了与标题中所提出的不同的问题。我不是想要Foo的FooBar,我是想要获取Foo的FooBar的Str。 - claudekennilol
谢谢。我以为我已经尝试过了,但可能在某个地方打错了字。实际上,这应该像它本来应该的那样容易。 - claudekennilol
如果您有一个 var f = new Foo() 的实例,在 object bar = getter.Invoke(f, null); 之后,bar 仍将为 null,并且 bar.GetType()... 将失败并引发 NullReferenceException,对吗?我有遗漏什么吗? - Marcelo Scofano Diniz

9

有一种方法可以稍微简化Andrew的答案

将调用GetGetMethod() + Invoke()替换为单个调用GetValue()

PropertyInfo barGetter =
    typeof(Foo).GetProperty("FooBar", BindingFlags.NonPublic | BindingFlags.Instance);
object bar = barGetter.GetValue(f);

PropertyInfo strGetter =
    bar.GetType().GetProperty("Str", BindingFlags.NonPublic | BindingFlags.Instance);
string val = (string)strGetter.GetValue(bar);

我进行了一些测试,没有发现区别,后来我找到了这个答案,它表明GetValue()调用GetGetMethod()并进行错误检查,所以实际上没有区别(除非你关心性能,但是在使用反射时我想你不会那么担心)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接