C# 中类属性扁平化的实现

46 阅读3分钟

前言

在开发中,我们经常会遇到需要将对象的属性扁平化处理的场景。这种需求尤其常见于对象序列化,或者与不支持嵌套结构的接口进行交互时。

本文将详细介绍如何在 C# 中实现一个包含多个子类的对象属性扁平化。通过几个完整且实用的示例,你将掌握这一功能的具体实现方法,并能够灵活应用于实际开发中。

理解"属性扁平化"

属性扁平化(Flattening Attributes)是指将具有嵌套结构的对象转换为单一层次结构的过程。

通过递归访问嵌套对象的属性,将其展开并合并到根对象的层次中。这一操作在处理对象序列化或与不支持复杂嵌套结构的系统交互时尤为有用。

示例代码

示例 简单扁平化

假设我们有一个 Person 类,其中包含一个 Address 子类。

我们希望将 Person 的属性,以及 Address 中的属性都提取到一个巩固的平面结构中。

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

publicclass Address
{
    publicstring Street { get; set; }
    publicstring City { get; set; }
}

publicclass Person
{
    publicstring Name { get; set; }
    publicint Age { get; set; }
    public Address Address { get; set; }
}

publicclass FlatObject
{
    publicstatic IDictionary<string, object> Flatten(object source)
    {
        if (source == null)
            thrownew ArgumentNullException(nameof(source));

        var result = new Dictionary<string, object>();
        Type type = source.GetType();

        foreach (PropertyInfo property in type.GetProperties())
        {
            object value = property.GetValue(source);
            if (value != null && !IsSimpleType(property.PropertyType))
            {
                var nestedProperties = Flatten(value);
                foreach (var nestedProperty in nestedProperties)
                {
                    result[$"{property.Name}.{nestedProperty.Key}"] = nestedProperty.Value;
                }
            }
            else
            {
                result[property.Name] = value;
            }
        }

        return result;
    }

    private static bool IsSimpleType(Type type)
    {
        return type.IsPrimitive || type.IsEnum || type == typeof(string);
    }
}

class Program
{
    static void Main()
    {
        Person person = new Person
        {
            Name = "John Doe",
            Age = 30,
            Address = new Address
            {
                Street = "123 Main St",
                City = "Anytown"
            }
        };

        IDictionary<string, object> flatPerson = FlatObject.Flatten(person);

        foreach (var property in flatPerson)
        {
            Console.WriteLine($"{property.Key}: {property.Value}");
        }
    }
}

运行结果:

示例:处理更复杂的嵌套结构

为了说明更复杂的情况,让我们扩展 Person 类,在其中添加对另一个类 Company 的引用。

static void Main()
{
    Person person = new Person
    {
        Name = "张三",
        Age = 30,
        Address = new Address
        {
            Street = "中山路123号",
            City = "北京"
        },
        Company = new Company
        {
            Name = "科技有限公司",
            Address = new Address
            {
                Street = "科技大道456号",
                City = "上海"
            }
        }
    };

    IDictionary<string, object> flatPerson = FlatObject.Flatten(person);

    foreach (var property in flatPerson)
    {
        Console.WriteLine($"{property.Key}: {property.Value}");
    }
}

运行结果:

总结

通过这两个示例,我们演示了如何将复杂对象的属性扁平化为字典结构。此过程采用递归方法,逐个遍历每个属性。如果某个属性本身仍然是一个复杂对象,则继续递归深入,直到提取出所有基本属性,并将结果合并到一起。这种技术在处理复杂数据结构时特别有用,尤其适用于与RESTful API交互、JSON格式化以及日志记录等场景。

希望本文能帮助大家在实际应用中更有效地进行对象属性的扁平化操作。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!