如何使用Reflection获取类及其基类(在层次结构中)的所有属性? (C#)

时间:2022-11-22 21:38:50

So what I have right now is something like this:

所以我现在所拥有的是这样的:

PropertyInfo[] info = obj.GetType().GetProperties(BindingFlags.Public);

where obj is some object.

其中obj是某个对象。

The problem is some of the properties I want aren't in obj.GetType() they're in one of the base classes further up. If I stop the debugger and look at obj, the I have to dig through a few "base" entries to see the properties I want to get at. Is there some binding flag I can set to have it return those or do I have to recursively dig through the Type.BaseType hierarchy and do GetProperties on all of them?

问题是我想要的一些属性不在obj.GetType()中,它们位于其中一个基类中。如果我停止调试器并查看obj,我必须挖掘一些“基础”条目以查看我想要获得的属性。是否有一些绑定标志我可以设置它返回那些或我是否必须递归挖掘Type.BaseType层次结构并对所有这些进行GetProperties?

5 个解决方案

#1


23  

Use this:

PropertyInfo[] info = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

EDIT: Of course the correct answer is that of Jay. GetProperties() without parameters is equivalent to GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static ). The BindingFlags.FlattenHierarchy plays no role here.

编辑:当然,正确答案是杰伊。不带参数的GetProperties()等效于GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)。 BindingFlags.FlattenHierarchy在这里不起作用。

#2


12  

I don't think it's that complicated.

我认为这并不复杂。

If you remove the BindingFlags parameter to GetProperties, I think you get the results you're looking for:

如果您将BindingFlags参数移除到GetProperties,我想您会得到您正在寻找的结果:

    class B
    {
        public int MyProperty { get; set; }
    }

    class C : B
    {
        public string MyProperty2 { get; set; }
    }

    static void Main(string[] args)
    {
        PropertyInfo[] info = new C().GetType().GetProperties();
        foreach (var pi in info)
        {
            Console.WriteLine(pi.Name);
        }
    }

produces

    MyProperty2
    MyProperty

#3


5  

If you access Type.BaseType, you can get the base type. You can recursively access each base type and you'll know when you've hit the bottom when your type is System.Object.

如果访问Type.BaseType,则可以获取基本类型。您可以递归访问每个基类型,当您的类型为System.Object时,您将知道何时触及底部。

Type type = obj.GetType();
PropertyInfo[] info = type.GetProperties(BindingFlags.Public);
PropertyInfo[] baseProps = type.BaseType.GetProperties(BindingFlags.Public);

#4


3  

I would tend to agree with Nicolas; unless you know you need reflection, then ComponentModel is a viable alternative, with the advantage that you will get the correct metadata even for runtime models (such as DataView/DataRowView).

我倾向于同意尼古拉斯;除非您知道需要反射,否则ComponentModel是一个可行的替代方案,其优点是即使对于运行时模型(例如DataView / DataRowView),您也将获得正确的元数据。

For example:

    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
    {
        Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj));
    }

As an aside, you can also do some simple performance tricks with this; you can do the same with reflection and Delegate.CreateDelegate, but there is no centralised place to hide the logic away, unlike TypeDescriptor with a TypeDescriptionProvider (don't worry if these are unfamiliar; you can just use the code "as is" ;-p).

顺便说一句,你也可以做一些简单的表演技巧;您可以使用反射和Delegate.CreateDelegate执行相同的操作,但是没有集中的地方可以隐藏逻辑,不像TypeDescriptor和TypeDescriptionProvider(不要担心这些是不熟悉的;您可以“按原样”使用代码; -p)。

#5


2  

Use:

TypeDescriptor.GetProperties(obj);

#1


23  

Use this:

PropertyInfo[] info = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

EDIT: Of course the correct answer is that of Jay. GetProperties() without parameters is equivalent to GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static ). The BindingFlags.FlattenHierarchy plays no role here.

编辑:当然,正确答案是杰伊。不带参数的GetProperties()等效于GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)。 BindingFlags.FlattenHierarchy在这里不起作用。

#2


12  

I don't think it's that complicated.

我认为这并不复杂。

If you remove the BindingFlags parameter to GetProperties, I think you get the results you're looking for:

如果您将BindingFlags参数移除到GetProperties,我想您会得到您正在寻找的结果:

    class B
    {
        public int MyProperty { get; set; }
    }

    class C : B
    {
        public string MyProperty2 { get; set; }
    }

    static void Main(string[] args)
    {
        PropertyInfo[] info = new C().GetType().GetProperties();
        foreach (var pi in info)
        {
            Console.WriteLine(pi.Name);
        }
    }

produces

    MyProperty2
    MyProperty

#3


5  

If you access Type.BaseType, you can get the base type. You can recursively access each base type and you'll know when you've hit the bottom when your type is System.Object.

如果访问Type.BaseType,则可以获取基本类型。您可以递归访问每个基类型,当您的类型为System.Object时,您将知道何时触及底部。

Type type = obj.GetType();
PropertyInfo[] info = type.GetProperties(BindingFlags.Public);
PropertyInfo[] baseProps = type.BaseType.GetProperties(BindingFlags.Public);

#4


3  

I would tend to agree with Nicolas; unless you know you need reflection, then ComponentModel is a viable alternative, with the advantage that you will get the correct metadata even for runtime models (such as DataView/DataRowView).

我倾向于同意尼古拉斯;除非您知道需要反射,否则ComponentModel是一个可行的替代方案,其优点是即使对于运行时模型(例如DataView / DataRowView),您也将获得正确的元数据。

For example:

    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
    {
        Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj));
    }

As an aside, you can also do some simple performance tricks with this; you can do the same with reflection and Delegate.CreateDelegate, but there is no centralised place to hide the logic away, unlike TypeDescriptor with a TypeDescriptionProvider (don't worry if these are unfamiliar; you can just use the code "as is" ;-p).

顺便说一句,你也可以做一些简单的表演技巧;您可以使用反射和Delegate.CreateDelegate执行相同的操作,但是没有集中的地方可以隐藏逻辑,不像TypeDescriptor和TypeDescriptionProvider(不要担心这些是不熟悉的;您可以“按原样”使用代码; -p)。

#5


2  

Use:

TypeDescriptor.GetProperties(obj);