递归获取类的属性和子属性

HoK*_*y22 33 c# reflection recursion

我正在做一些像递归获取对象的属性和子属性的东西 ,但我想以递归方式使用反射来获取每个属性.我从递归打印属性中获取代码.

代码的问题是:它只降低了一级,我想知道如何使用反射自动获取所有属性?我刚刚编写了以下示例Container代码:

public class Container
{
    public Bottle MyBottle { get; set; }
    public List<Address> Addresses { get; set; }

    public Container()
    {
        Address a = new Address();
        a.AddressLine1 = "1 Main St";
        a.AddressLine2 = "2 Main St";
        Addresses = new List<Address>();
        Addresses.Add(a);

        MyBottle = new Bottle();
        MyBottle.BottleName = "Big bottle";
        MyBottle.BottageAge = 2;
    }
}

public class Bottle
{
    public string BottleName { get; set; }
    public int BottageAge { get; set; }
}

public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public List<SpecialFolder> SpecialFolders { get; set; }

    public Address()
    {
        SpecialFolders = new List<SpecialFolder>();
        SpecialFolder sf = new SpecialFolder();
        sf.TemplateFolder = Environment.SpecialFolder.Templates.ToString();
        sf.UserFolder = Environment.SpecialFolder.UserProfile.ToString();
        SpecialFolders.Add(sf);
    }
}

public class SpecialFolder
{
    public string TemplateFolder { get; set; }
    public string UserFolder { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在Main方法中:

static void Main(string[] args)
{
    Container c = new Container();
    PrintProperties(c);
}
public static void PrintProperties(object obj)
{
    PrintProperties(obj, 0);
}
public static void PrintProperties(object obj, int indent)
{

    if (obj == null) return;
    string indentString = new string(' ', indent);
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        object propValue = property.GetValue(obj, null);
        if (property.PropertyType.Assembly == objType.Assembly)
        {
            Console.WriteLine("{0}{1}:", indentString, property.Name);

            PrintProperties(propValue, indent + 2);
        }
        else
        {
            Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望得到:

MyBottle:
      BottleName: Big bottle
      BottageAge: 2
Addresses:
      AddressLine1: 1 Main St
      AddressLine2: 2 Main St
      SpecialFolders:
            TemplateFolder: Templates
            UserFolder: UserProfile
Run Code Online (Sandbox Code Playgroud)

我现在得到的结果:

MyBottle:
  BottleName: Big bottle
  BottageAge: 2
Addresses: System.Collections.Generic.List`1[TreeViewReflectionExample.Address]
Run Code Online (Sandbox Code Playgroud)

有人可以帮我使用PrintProperties方法吗?非常感谢你.

Kon*_*osa 52

您的代码有两个问题:

  1. 由于条件if (property.PropertyType.Assembly == objType.Assembly),你会忽略System.CollectionsList<>
  2. 你不区别对待propValue集合.因此,它将打印List属性,而不是其元素属性.

您可以将其更改为:

public void PrintProperties(object obj, int indent)
{    
    if (obj == null) return;
    string indentString = new string(' ', indent);
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        object propValue = property.GetValue(obj, null);
        var elems = propValue as IList;
        if (elems != null)
        {
            foreach (var item in elems)
            {
                PrintProperties(item, indent + 3);
            }
        }
        else
        {
            // This will not cut-off System.Collections because of the first check
            if (property.PropertyType.Assembly == objType.Assembly)
            {
                Console.WriteLine("{0}{1}:", indentString, property.Name);

                PrintProperties(propValue, indent + 2);
            }
            else
            {
                Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 正是我正在寻找的,不仅适用于这个例子,而且适用于我拥有的所有其他情况 (3认同)
  • C#6语法糖的一个不错的小窍门:`if(propValue是IList elems)工作并保存一行。 (2认同)

dri*_*iis 13

您希望分别处理基本类型和字符串,并循环遍历可枚举而不是仅仅获取其ToString()值.所以你的代码可以更新为:

public void PrintProperties(object obj, int indent)
{

    if (obj == null) return;
    string indentString = new string(' ', indent);
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    foreach (PropertyInfo property in properties)
    {   
        object propValue = property.GetValue(obj, null);
        if(property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
            Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
        else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
        {
            Console.WriteLine("{0}{1}:", indentString, property.Name);
            IEnumerable enumerable = (IEnumerable)propValue;
            foreach(object child in enumerable)
                PrintProperties(child, indent + 2);
        }
        else 
        {
            Console.WriteLine("{0}{1}:", indentString, property.Name);
            PrintProperties(propValue, indent + 2);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)