在.NET& C#,假设ClassB
的字段类型为ClassA
。
可以轻松使用方法GetFields
列出ClassB
的字段。
但是,我希望还列出自己包含字段的ClassB
字段的字段。
例如,ClassB
的字段x
包含字段b
,s
和i
。我想(以编程方式)列出这些字段(正如我在以下代码中的评论所示)。
class ClassA
{
public byte b ;
public short s ;
public int i ;
}
class ClassB
{
public long l ;
public ClassA x ;
}
class MainClass
{
public static void Main ( )
{
ClassA myAObject = new ClassA () ;
ClassB myBObject = new ClassB () ;
// My goal is this:
// ***Using myBObject only***, print its fields, and the fields
// of those fields that, *themselves*, have fields.
// The output should look like this:
// Int64 l
// ClassA x
// Byte b
// Int16 s
// Int32 i
}
}
答案 0 :(得分:7)
使用FieldInfo.FieldType
反映班级中字段的类型。 E.g。
fieldInfo.FieldType.GetFields();
以下是基于您的代码的完整示例,如果您在ClassZ
内ClassA
,则会使用递归。如果你有一个循环对象图,它就会中断。
using System;
using System.Reflection;
class ClassA {
public byte b;
public short s;
public int i;
}
class ClassB {
public long l;
public ClassA x;
}
class MainClass {
public static void Main() {
ClassB myBObject = new ClassB();
WriteFields(myBObject.GetType(), 0);
}
static void WriteFields(Type type, Int32 indent) {
foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) {
Console.WriteLine("{0}{1}\t{2}", new String('\t', indent), fieldInfo.FieldType.Name, fieldInfo.Name);
if (fieldInfo.FieldType.IsClass)
WriteFields(fieldInfo.FieldType, indent + 1);
}
}
}
答案 1 :(得分:6)
执行此操作的类已经存在!看一下Visual Studio的Microsoft C#示例:http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=csharpsamples&ReleaseId=8
具体来说,请查看ObjectDumper示例,因为它深入n级。例如:
ClassB myBObject = new ClassB();
...
ObjectDumper.Write(myBObject, Int32.MaxValue);
//Default 3rd argument value is Console.Out, but you can use
//any TextWriter as the optional third argument
它已经考虑了图表中的对象是否已被访问,值类型与对象类型与可枚举类型等等。
答案 2 :(得分:1)
尝试以下方法。它允许您控制下降到类型层次结构的深度,并且只应该下降到非基本类型。
public static class FieldExtensions
{
public static IEnumerable<FieldInfo> GetFields( this Type type, int depth )
{
if( depth == 0 )
return Enumerable.Empty<FieldInfo>();
FieldInfo[] fields = type.GetFields();
return fields.Union(fields.Where( fi => !fi.IsPrimitive )
.SelectMany( f => f.FieldType.GetFields( depth -1 ) );
}
}
答案 3 :(得分:0)
您需要编写一个递归方法,该方法接受一个对象,遍历其字段(obj.GetType().GetFields()
),并打印基本类型字段的值,并为一个类调用自身({{1除外) }})。
缩进大小需要一个参数用于递归。
编辑:您还需要一些机制来防止循环对象图的堆栈溢出。我建议对缩进参数设置限制。
答案 4 :(得分:0)
这是一个天真的实现:
private static void ListFields(Type type)
{
Console.WriteLine(type.Name);
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
Console.WriteLine(string.Format("{0} of type {1}", field.Name, field.FieldType.Name));
if (field.FieldType.IsClass)
{
ListFields(field.FieldType);
}
}
}
有些注意事项: