我不知道主题的标题是否正确,但这就是我想要的。
假设我有一个班级,而这个班级可以有另一个班级,依此类推。
我想要的是,获取类的字段,最终在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);
}
}
}
但它只到达第一级。第一个参数是我想要分解的对象,第二个参数是返回类的列表对象。 你能帮帮我们吗? 感谢。
答案 0 :(得分:1)
这种东西非常适合编写测试以找出方法!
简而言之,您想要的方法非常类似:
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;
}
}
}
答案 1 :(得分:0)
我认为问题是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);
}
}
}
答案 2 :(得分:0)
我终于成功完成了这项工作。 对于想要实际代码的人来说,这里是:
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);
}
}
}