0

我不知道主题的标题是否正确,但这就是我想要的。

假设我有一个班级,而它又可以有另一个班级,依此类推。

我想要的是获得类的字段,最终在 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);
                }
            }                                                
        }

但它只能达到第一级。第一个参数是我要分解的对象,第二个参数是返回类的列表对象。你们能帮帮我吗?谢谢。

4

3 回答 3

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;
        }

    }
}
于 2013-08-30T19:07:43.580 回答
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);
           }
       }
    }
于 2013-08-30T19:25:54.880 回答
0

我认为问题在于 fi.GetType() 不返回类型“地址”而是返回 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);
        }
    }                                                
}
于 2013-08-30T17:47:01.097 回答