c递归分解类
本文关键字:分解 递归 | 更新日期: 2023-09-27 18:29:44
我不知道主题的标题是否正确,但这是我想要的。
假设我有一个类,然后可以有另一个类等等
我想要的是获得类的字段,最终在具有多个级别的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);
}
}
}