我想创建一个字典,其中将对象的所有公共属性映射到纯字符串属性名称。例如,以下“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;
}
字典结果:
物业名称 | 完整路径 |
---|---|
|
|
|
|
|
|
|
|
|
|
虽然我不明白为什么你需要这样做,但你可以使用反射来获取你需要的所有数据:
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);
}
}
输出:
抱歉我没有很好地解释我的问题。我想让它远离问题的实际核心,但我认为这最终变得更加混乱。
本质上,我有一个 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++ );
}