在.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
}
}
使用FieldInfo.FieldType
反映过来在你的类中的字段的类型。 例如
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);
}
}
}
这确实类这已经存在! 看看微软C#示例为Visual Studio: http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=csharpsamples&ReleaseId=8
具体来说,看ObjectDumper样品,因为它去正层次深。 例如:
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
它已经考虑到无论是在图形对象已被访问,值类型与对象类型与枚举类型,等等。
请尝试以下操作。 它可以让你控制你有多深下降到类型层次,只能沦落成非基本类型。
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 ) );
}
}
你需要编写需要的对象的递归方法,遍历其字段( obj.GetType().GetFields()
并打印原始类型的字段的值,并自称为一个类(而不是String
) 。
你需要为递归使用缩进大小的参数。
编辑 :您还需要一些机制来防止用于循环对象图堆栈溢出。 我建议将限制在缩进参数。
这里有一个天真的实现:
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);
}
}
}
需要注意以下几点:
- 防止堆栈溢出。 也就是说,如果A - > B和B-> A,那么这将炸毁。 您可以通过只解决到一定程度解决此
- 字符串是引用类型,但很多人希望它更像是一个值类型。 所以,你可能不想打电话ListFields如果类型为字符串。