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

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

c递归分解类

这种东西非常适合编写测试来找出前进的道路!

简而言之,你想要的方法很像:

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