[英]c# recursively decompose class
我不知道该主题的标题是否正确,但这就是我想要的。
假设我有一个类,而该类又可以具有另一个类,依此类推。
我想要的是获取类的字段,最终在具有多个级别的List泛型中。
例如,假设我有这个:
class address
{
public string street;
public string number;
}
class Student
{
public string name;
public string surname;
public address addr;
}
例如,我需要一个方法
Student s;
getItems(s);
这将返回一个包含以下内容的列表:名称,姓氏以及另一个包含街道和号码的列表。
我尝试了这个:
public void getItems(Object o, List<object> list)
{
FieldInfo[] f = new FieldInfo[o.GetType().GetFields().Length];
f = o.GetType().GetFields();
foreach (FieldInfo fi in f)
{
if (fi.GetType().GetFields().Length > 0)
{
List<object> newList = new List<object>();
list.Add(newList);
getItems(fi, newList);
}
else
{
list.Add(fi.Name);
}
}
}
但它只能达到第一级。 第一个参数是我要分解的对象,第二个参数是将返回类的列表对象。 你能帮我吗? 谢谢。
这种事情非常适合编写测试以找出前进的方向!
简而言之,您想要的方法非常类似于:
List<string> GetFieldNames(IEnumerable<FieldInfo> fields)
{
var results = new List<string>();
foreach (var fieldInfo in fields)
{
if (fieldInfo.FieldType.GetFields().Count() > 1)
{
results.AddRange(GetFieldNames(fieldInfo.FieldType.GetFields()));
}
else
{
results.Add(fieldInfo.Name);
}
}
return results;
}
完整的测试类演示了该功能(并弄清楚了)是:
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
namespace stackoverflow_tests
{
[TestFixture]
public class ReflectionTest
{
class Address
{
public string Street;
public string Number;
}
class Student
{
public string Name;
public string Surname;
public Address Address;
}
[Test]
public void ShouldDisplayNestedClassFields()
{
var student = new Student();
var studentFields = student.GetType().GetFields();
Assert.IsNotNull(studentFields);
Assert.AreEqual(3, studentFields.Count());
var expectedNames = new []{"Name", "Surname", "Address"};
var expectedTypes = new[] {typeof(string), typeof(string), typeof(Address)};
for (var fieldIndex = 0; fieldIndex < 3; fieldIndex++)
{
var field = studentFields[fieldIndex];
var fieldName = field.Name;
Assert.AreEqual(expectedNames[fieldIndex], fieldName);
var fieldType = field.FieldType;
Assert.AreEqual(expectedTypes[fieldIndex], fieldType);
var childFields = field.FieldType.GetFields();
var childFieldCount = childFields.Count();
var expectedFieldCount = fieldIndex == 2 ? 2 : 1;
Assert.AreEqual(expectedFieldCount, childFieldCount);
}
}
[Test]
public void CanGetFieldNames()
{
var expectedResults = new List<string> {"Name", "Surname", "Street", "Number"};
var student = new Student();
var actual = GetFieldNames(student.GetType().GetFields());
Assert.AreEqual(expectedResults, actual);
}
List<string> GetFieldNames(IEnumerable<FieldInfo> fields)
{
var results = new List<string>();
foreach (var fieldInfo in fields)
{
if (fieldInfo.FieldType.GetFields().Count() > 1)
{
results.AddRange(GetFieldNames(fieldInfo.FieldType.GetFields()));
}
else
{
results.Add(fieldInfo.Name);
}
}
return results;
}
}
}
我认为问题在于fi.GetType()不会返回类型“ address”,而是返回FieldInfo ...
您可能要测试fi.FieldType ...
public static void getItems(Object o, List<object> list)
{
FieldInfo[] f = new FieldInfo[o.GetType().GetFields().Length];
f = o.GetType().GetFields();
foreach (FieldInfo fi in f)
{
if (fi.FieldType.GetFields().Length > 0)
{
List<object> newList = new List<object>();
list.Add(newList);
getItems(fi, newList);
}
else
{
list.Add(fi.Name);
}
}
}
我终于设法做到了。 对于需要实际代码的人,这里是:
public void getItems(Type t, List<object> list)
{
foreach(FieldInfo fi in t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic))
{
list.Add(fi.Name);
if(!fi.FieldType.Namespace.Equals("System"))
{
List<object> newList = new List<object>();
list.Add(newList);
getItems(fi.FieldType, newList);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.