C# 创建字典,将所有非对象属性名称映射到对象的结构

问题描述 投票:0回答:2

我想创建一个字典,其中将对象的所有公共属性映射到纯字符串属性名称。例如,以下“Person”类应返回以下字典。我想我想用

.GetProperties()
方法遍历对象树,但我不知道从那里去哪里。

代码:

public class Person
{
    public string FirstName;
    public string LastName;
    public Address Addr;
}

public class Address
{
    public string Country;
    public City City;
}

public class City
{
    public string ZipCode;
    public string Street;
}

字典结果:

物业名称 完整路径
FirstName
FirstName
LastName
LastName
Country
Addr.Country
ZipCode
Addr.City.ZipCode
Street
Addr.City.Street
c# linq
2个回答
0
投票

虽然我不明白为什么你需要这样做,但你可以使用反射来获取你需要的所有数据:

void PropertyToDictionary()
{
    Person person = new()
    {
        FirstName = "Johnny",
        LastName = "Depp",
        Addr = new()
        {
            City = new()
            {
                Street = "Street",
                ZipCode = "12345"
            }
        }
    };

    var dic =new Dictionary<string, string>();

    person.GetType()
        .GetProperties()
        .ToList()
        .ForEach(p =>
        {
            if (p.Name == "Addr")
            {
                p.GetValue(person)
                .GetType()
                .GetProperties()
                .ToList()
                .ForEach(pp =>
                {
                    if (pp.Name == "City")
                    {
                        pp.GetValue(person.Addr)
                        .GetType()
                        .GetProperties()
                        .ToList()
                        .ForEach(ppc =>
                        {
                            dic.Add(ppc.Name, $"{p.Name}.{pp.Name}.{ppc.Name}");
                        });
                    }
                    else
                    {
                        dic.Add(pp.Name, $"{p.Name}.{pp.Name}");
                    }
                });
            }
            else
            {
                dic.Add(p.Name,p.Name);
            }
        });

    foreach (var item in dic)
    {
        Console.WriteLine(item.Key + "-----" + item.Value);
    }
}

输出:

Output console


0
投票

抱歉我没有很好地解释我的问题。我想让它远离问题的实际核心,但我认为这最终变得更加混乱。

本质上,我有一个 Web 项目,它发出对数据库实体进行搜索、排序等的请求。请求仅包含一个字符串作为应使用的属性,然后包含请求的类型。该属性代码位于顶层或嵌套。因此,我需要构建一种方法来获取我可以使用的可能的顶级和嵌套属性,并将其映射到简单的名称。最后,只是一个包含所有公共顶级属性和嵌套属性的动态字典。

这是我最终解决它的方法:

/// <summary>
/// This method will populate the <paramref name="propertiesDictionary"/> with keys of all of the public property and nested
/// public properties. This is useful for mapping search, sort, etc. requests with the request property to the fully pathed
/// with the object property name. The values of the dictionary can then be used in linq queries to pull the data from the entities.
/// Important notes:
///     1. This will only use the top most level property name if there are multiple properties with the same name.
///     2. This will not handle nested objects of the same type.
///     3. It requires all objects to reside in the same namespace. This is needed to ignore properties on strings, Lists, etc. However, this means only objects in that namespace will be used.
/// </summary>
/// <param name="objectType">The type of the object that will be pulled from</param>
/// <param name="propertiesDictionary">The dictionary that will be populated with the plain string names as the keys and the full pathed property has the value</param>
/// <param name="objectNameSpace">The namespace of the properties</param>
/// <param name="prefix">Prefix used in the recursive call to fill out the full path. THIS SHOULD BE EMPTY ON THE FIRST CALL</param>
/// <param name="topLevelObject">The top level object that we are using. THIS SHOULD BE NULL ON THE FIRST CALL</param>
/// <param name="recursionIteration">The current iteration of recursive which is used to bail to avoid a stack-overflow. THIS SHOULD BE ZERO ON THE FIRST CALL</param>
private static void GetPublicPropertiesAndNestedPropertiesRecursively( Type objectType, IDictionary<string, string> propertiesDictionary, string objectNameSpace, string prefix = "", Type topLevelObject = null, int recursionIteration = 0 )
{
    // First, check to make sure that we didn't hit the recursion max
    if ( recursionIteration > 8 )
    {
        return;
    }

    // If this is not the first call, bail out if this is the same object. This would cause an infinite loop if not. 
    // If this is the first call, set the top level object.
    if ( topLevelObject == null )
    {
        topLevelObject = objectType;
    }
    else if ( objectType == topLevelObject )
    {
        return;
    }

    // Get all the public properties and return if there is no or th
    var currentProperties = objectType.GetProperties();
    if ( objectType.GetProperties().Length < 1 || objectType.Namespace == null || !objectType.Namespace.StartsWith( objectNameSpace ) )
    {
        return;
    }

    // Add all of the properties that currently don't exist
    foreach ( var currentProperty in currentProperties.Where( currentProperty => !propertiesDictionary.ContainsKey( currentProperty.Name.ToLower() ) ) )
    {
        propertiesDictionary.Add( currentProperty.Name.ToLower(), $"{prefix}{currentProperty.Name}".ToLower() );
    }

    // Recursively get all of the nested properties
    foreach ( var propertyInfo in currentProperties )
    {
        GetPublicPropertiesAndNestedPropertiesRecursively( propertyInfo.PropertyType, propertiesDictionary, objectNameSpace, $"{propertyInfo.Name}.",  topLevelObject, recursionIteration++ );
    }
© www.soinside.com 2019 - 2024. All rights reserved.