【问题标题】:C# Iterate through nested properties using IEnumeratorC# 使用 IEnumerator 遍历嵌套属性
【发布时间】:2020-04-25 06:46:10
【问题描述】:

我在列表和数组或字典上看到了 IEnumerator 的示例(和官方示例),但我有一个不同的问题。我有带属性的类,在这种情况下如何实现 IEnumerable 和 IEnumerator?

我的属性类是:

public class standardMessage
{
    public messageProperties message { get; set; }
    public messageFlag flag { get; set; }
}

public class messageProperties
{
    public string messageSubject { get; set; }
    public string messageBody { get; set; }
}

public class messageFlag
{
    public Boolean flagImportant { get; set; }
    public Boolean flagPersonal { get; set; }
}

这就是程序:

public class Program
{
    static void Main(string[] args)
    {
        standardMessage myMessage = new standardMessage();

        myMessage.message = new messageProperties
        {
            messageSubject = "Greetings",
            messageBody = "Happy Weekend"
        };

        myMessage.flag = new messageFlag
        {
            flagImportant = false,
            flagPersonal = true
        };

        //how do I iterate through all properties, without knowing how many are there, instead of writing this worm line of code?
        Console.WriteLine(myMessage.message.messageSubject.ToString() + "\r\n" + myMessage.message.messageBody.ToString() + "\r\n" + myMessage.flag.flagImportant.ToString() + "\r\n" + myMessage.flag.flagPersonal.ToString());
        Console.ReadLine();
    }
}

【问题讨论】:

  • 在这种情况下,您可能只想覆盖类的ToString 方法。
  • 好吧,你已经有类似的问题C# how to implement IEnumerable for nested classes
  • 使用反射可以获得所有类属性的 IEnumerable。然后,您可以遍历属性以获取嵌套在其中的任何属性,就像遍历任何其他树结构一样。
  • @Pavel Anikhouski 感谢您指出其他解决方案;但是,它没有实现 IEnumerable(尽管属性是单例,但我一直在寻找 List 解决方案,但无论如何),更重要的是,当我实现时,我发现它不返回“子”属性。例如,对于我们这里的问题,我希望不仅“看到”“消息”和“标志”,而且“看到”“消息”中的“消息主题”和“消息正文”——对于“标志重要”和“标志个人”也是如此在标准消息的“标志”内。

标签: c# properties ienumerable ienumerator


【解决方案1】:

我做了一个非常原始的对象到 json 转换器。我不会在生产中使用它,它比 Newtonsoft 慢约 30%,但它完成了工作。

private static string PrintObject(object obj, int depth = 1)
{
    var type = obj.GetType();
    if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String))
        return "\"" + obj.ToString() + "\"";
    var props = type.GetProperties();
    string ret = "";
    for (var i = 0; i < props.Length; i++)
    {
        var val = props[i].GetValue(obj);
        ret += new string('\t', depth) + "\"" + props[i].Name + "\":" + PrintObject(val, depth + 1);
        if (i != props.Length - 1)
            ret += "," + Environment.NewLine;
    }

    return ("{" + Environment.NewLine + ret + Environment.NewLine + new string('\t', depth - 1) + "}").Replace("\t", "  ");
}

给出结果

{
  "message":{
    "messageSubject":"Greetings",
    "messageBody":"Happy Weekend"
  },
  "flag":{
    "flagImportant":"False",
    "flagPersonal":"True"
  }
}

【讨论】:

  • 非常感谢,我把它放在没有私有静态的 Main 中,并按照您的描述工作。我可以问一件事吗?我通常不知道深度,如何修改以搜索到嵌套属性的最后一级?非常感谢!!
  • 不要为深度参数添加任何内容。当您调用它时,它将从 1 开始,并在每次调用时递归递增。如果要打印嵌套对象,只需调用 PrintObject(myMessage.flag);
  • 如果这解决了您的问题,您能否将其标记为已回答?谢谢!
【解决方案2】:

如果您想要一种将对象打印为格式化字符串的生产级方式,您需要在所有类中覆盖 ToString 以返回您想要的任何格式。

但是,如果您只是想在屏幕上打印内容以进行调试或记录,为什么不使用 JSON?

public static string ToJson(object @object) =>
    System.Text.Json.JsonSerializer.Serialize(@object, new JsonSerializerOptions{WriteIndented = true});
Console.WriteLine(ToJson(myMessage));

打印

{
  "message": {
    "messageSubject": "Greetings",
    "messageBody": "Happy Weekend"
  },
  "flag": {
    "flagImportant": false,
    "flagPersonal": true
  }
}

又快又脏,但又快又好用。

【讨论】:

  • 非常感谢,请问,我收到 System.Text.Json 的错误(因为 System.Text 中不存在 Json)-您的建议?
  • @Nick System.Text.Json 来自 .NET Core 3.0,如果您使用的是 Framework 或旧版 Core,请获取 System.Text.Json NuGet package
  • 谢谢你,它按照你的建议工作。我只是想知道我是否可以在没有 Json 的情况下做到这一点(在另一个环境中安装 Nuget 时出现问题,您的回答绝对没有问题..)
  • @Nick 你可以自己写一个序列化器,但这很麻烦。那时你最好自己覆盖ToString
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
相关资源
最近更新 更多