【问题标题】:Best way to iterate through all fields and nested fields in object遍历对象中所有字段和嵌套字段的最佳方法
【发布时间】:2020-12-13 00:14:19
【问题描述】:

我有一个问题,我从外部 api 接收对象,并在我的系统中反序列化为 c# 对象。这些对象记录在我的系统上,因此我需要能够清理它们。

我可以处理的对象结构的一个很好的例子可能是这个:

var person = new {
       Name = "Filip",
       friends = new string[] { "Lorem ipsum @exampel.com för s",                                                                          
                                "Ange mailasasa", "Ange mailadress på                                
                                  formen namn@exampel.com för s",
                                "Some random text",
                                "Ange mailadress på formen" },
       innerObj = new  { s = new List<string>() {
                                "nge mailadress på formen na.com för s",  
                                "Ange mailadress på formen amn@exampel.com för sökande: 920294-1801",
                                "Ange mailadress på formen namn@exampel.com fö"},
                          anotherField = "nldsa",
                        },
       Age = 24
};

具体来说,我需要检测子字符串“920294-1801”,这个问题的正则表达式部分不是我想问的。

我想知道查看对象的最佳方法,查看所有字符串类型的字段,以及嵌套在其他数据结构中的字段。在此处的示例中,我需要查看“InnerObj”,然后查看该列表中的列表元素。

那么有什么方法可以接收对象内的所有嵌套字符串字段并遍历它们?

编辑: 我可能应该澄清一下,我需要一种适用于不同内部结构对象的方法。这意味着它不应该只工作这个示例对象,而是许多不同结构的不同通用对象

编辑: 有人建议这个问题之前已经被问过,但它没有,因为没有其他问题正在寻找一种通用方法来从不同结构的对象中获取所有字段(+嵌套字段)

【问题讨论】:

  • 您这样做是为了替换字符串的所有实例吗?
  • 不,这个问题不涉及获取嵌套值
  • 取决于你的意思 tymfam,我可以在对象的任何地方找到的任何连续 10 次出现都应该被替换。但这不是问题所在,我只想遍历所有字段,包括嵌套字段

标签: c# asp.net


【解决方案1】:

我看到了 3 个选项:

  • 如果您知道对象的结构,请编写检查所有对象的代码。即使对于一个大物体,这也不应该花很长时间。如果添加了新属性,则必须扩展该方法。
  • 序列化对象,例如 JSON,执行正则表达式和反序列化。风险:如果您的替换更改了属性名称等,您可能会破坏对象。
  • 使用反射查找所有字符串属性。示例方法在:C#: How to get all public (both get and set) string properties of a type

【讨论】:

  • - 问题的整个想法是我不知道对象的结构 - 序列化可能是一个太大的操作,而且风险太大,我需要确定它不会中断 -我目前正在研究反射,但我的问题是关于查看嵌套字段,您链接的问题不包含解决方案
【解决方案2】:

首先,此代码会将对象的所有属性添加到 ArrayList 中,经常使用 Type 来了解如何解析每个实体(如字符串、数组或列表)并将其添加到 ArrayList :

using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

var person = new
{
    Name = "Filip",
    friends = new string[] { "Lorem ipsum @exampel.com för s",
                             "Ange mailasasa", "Ange mailadress på formen namn@exampel.com för s",
                             "Some random text",
                             "Ange mailadress på formen" },
    innerObj = new 
    { s = new List<string>()
        {
            "nge mailadress på formen na.com för s",
            "Ange mailadress på formen namn@exampel.com för sökande: 920294-1801",
            "Ange mailadress på formen namn@exampel.com fö"
        },
        anotherField = "nldsa",
    },
        Age = 24
};
    
var properties = GetProperties(person);
ArrayList propLst = new ArrayList();
    
foreach (var p in properties)
{
    string name = p.Name;
    var value = p.GetValue(person, null);
    Type valueType = value.GetType();
    if (valueType.IsArray) {
        string[] arr = ((IEnumerable)value).Cast<object>()
                       .Select(x => x.ToString())
                       .ToArray();
        for (int i = 0; i < arr.Length; i++)
        {
            propLst.Add(arr[i]);
        }
    }
    else if (value is string || value is int) {
        propLst.Add(value);
    }
    else {   // If not array or string or integer, it must be the (nested) object with a list inside
        var nestedObjectsProperties = p.PropertyType.GetProperties();
        foreach (var prop in nestedObjectsProperties) {
            var listObject = prop.GetValue(value, null);
            Type valueTypeInNestedObj = listObject.GetType();
            if (valueTypeInNestedObj.IsGenericType) {
                var collection = ((IEnumerable)listObject).Cast<object>().ToList();
                foreach (var val in collection) {
                   propLst.Add(val);   
                }
            }
            else {  // If not list, must be "anotherField"
                propLst.Add(listObject);
            }
        }
    } 
}
    
PrintValues(propLst);

private PropertyInfo[] GetProperties(object obj)
{
    return obj.GetType().GetProperties();
}

private void PrintValues(IEnumerable myList) {
  foreach (Object obj in myList)
     Console.WriteLine(obj);
}

从那里,您可以对冒号后的文本使用正则表达式或Split() 方法检测该子字符串,所有这些都通过遍历 ArrayList 中的字符串来实现。

【讨论】:

  • 这看起来很有趣,只是测试一下
  • 嗯,不,我害怕。此代码仅适用于显示的示例对象。我需要一种方法,可以让我拥有不同结构的对象的所有嵌套字段
  • 我知道这仅适用于您提供的示例,但您可以稍微调整代码以根据每个属性的Type 调整您收到的对象。我假设您收到的对象结构一致,因为它们来自 API。您能否提供更多从 API 获得的对象(我认为是 JSON)示例?
猜你喜欢
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
  • 2012-09-27
  • 2013-06-10
  • 1970-01-01
相关资源
最近更新 更多