c# - 你如何将一个扁平的点状属性列表转换为一个构造的对象?

标签 c# dynamic reflection recursion

我有一个属性列表及其值,它们的格式为 Dictionary<string, object>像这样:

Person.Name = "John Doe"
Person.Age = 27
Person.Address.House = "123"
Person.Address.Street = "Fake Street"
Person.Address.City = "Nowhere"
Person.Address.State = "NH"

有两个类。 Person由字符串 Name 组成和原始Age以及复杂的Address类有 House , Street , City , 和 State字符串属性。

基本上我想做的是查找类 Person在当前程序集中创建它的实例并分配所有值,无论类变得多么复杂,只要在最深层次上它们由基元、字符串和一些常见结构(如 DateTime)组成即可。 .

我有一个解决方案,允许我分配顶级属性并向下分配到复杂属性之一。我假设我必须使用递归来解决这个问题,但我不想这样做。

尽管如此,即使使用递归,我仍然无法找到一种深入了解每个属性并为其赋值的好方法。

在下面的这个例子中,我试图根据方法的参数将虚线表示转换为类。我根据参数的类型查找适当的点表示,试图找到一个匹配项。 DotField基本上是一个 KeyValuePair<string, object>其中关键是 Name属性(property)。下面的代码可能无法正常工作,但它应该足够好地表达了这个想法。

foreach (ParameterInfo parameter in this.method.Parameters)
{
    Type parameterType = parameter.ParameterType;
    object parameterInstance = Activator.CreateInstance(parameterType);

    PropertyInfo[] properties = parameterType.GetProperties();
    foreach (PropertyInfo property in properties)
    {
        Type propertyType = property.PropertyType;
        if (propertyType.IsPrimitive || propertyType == typeof(string))
        {
            string propertyPath = String.Format("{0}.{1}", parameterType.Name, propertyType.Name);
            foreach (DotField df in this.DotFields)
            {
                if (df.Name == propertyPath)
                {
                    property.SetValue(parameterInstance, df.Value, null);
                    break;
                }
            }
        }
        else
        {
            // Somehow dive into the class, since it's a non-primitive
        }
    }
}

最佳答案

您的 Dictionary 听起来类似于 JSON 格式的数据。如果先将其转换为兼容形式,则可以使用 Json.Net将字典转换为您的对象。这是一个例子:

public static void Main()
{
    var dict = new Dictionary<string, object>
    {
        {"Person.Name", "John Doe"},
        {"Person.Age", 27},
        {"Person.Address.House", "123"},
        {"Person.Address.Street", "Fake Street"},
        {"Person.Address.City", "Nowhere"},
        {"Person.Address.State", "NH"},
    };
    var hierarchicalDict = GetItemAndChildren(dict, "Person");
    string json = JsonConvert.SerializeObject(hierarchicalDict);
    Person person = JsonConvert.DeserializeObject<Person>(json);
    // person has all of the values you'd expect
}
static object GetItemAndChildren(Dictionary<string, object> dict, string prefix = "")
{
    object val;
    if (dict.TryGetValue(prefix, out val))
        return val;
    else
    {
        if (!string.IsNullOrEmpty(prefix))
            prefix += ".";
        var children = new Dictionary<string, object>();
        foreach (var child in dict.Where(x => x.Key.StartsWith(prefix)).Select(x => x.Key.Substring(prefix.Length).Split(new[] { '.' }, 2)[0]).Distinct())
        {
            children[child] = GetItemAndChildren(dict, prefix + child);
        }
        return children;
    }
}

关于c# - 你如何将一个扁平的点状属性列表转换为一个构造的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19431969/

相关文章:

c# - 如果我在 visual studio 中选择选项 "convert to web application",它会做什么?

c# - 字符串或二进制数据将被截断 WHERE IN

angularjs - Angular (1.5.8) 动态组件

java - 获取可从 java 源代码调用的类中的方法列表

java - 获取枚举下变量的值

c# - 在 WP7 上显示来自 Web 服务的 JSON 数据

c# - while循环用数组填充datagridview

css动态背景图片定位

javascript - 计算动态添加的输入中的值

java - 嵌套类中的反射