将 Dictionary<string, object> 转换为 class 和 subclass

Convert Dictionary<string, object> to class and subclass

如何将字典递归地转换为 class 和 subclasses? 这些是我的 classes:

public class UiItem
{
    public string id { get; set; }
    public string text { get; set; }
    public Rect rect { get; set; } 
}

public class Rect
{
    public int height { get; set; }
    public int width { get; set; }
    public int y { get; set; }
    public int x { get; set; }
}

我写了这个,但我不知道如何在 class UiItem:

中创建对象 Rect
public static T GetObject<T>(this Dictionary<string, object> dict)
    {
        Type type = typeof(T);
        var obj = Activator.CreateInstance(type);

        foreach (var kv in dict)
        {
            var prop = type.GetProperty(kv.Key);
            object value = kv.Value;
            if (kv.Value.GetType() == typeof(Dictionary<string, object>))
            {
                value = GetObject<_???_>((Dictionary<string, object>) value) // <= This line
            }

            if(prop == null) continue;
            prop.SetValue(obj, value, null);
        }
        return (T)obj;
    }

最简单的方法是将类型作为参数传递,而不是使用泛型方法。然后是:

public static Object GetObject(this Dictionary<string, object> dict, Type type)
    {
        var obj = Activator.CreateInstance(type);

        foreach (var kv in dict)
        {
            var prop = type.GetProperty(kv.Key);
            if(prop == null) continue;

            object value = kv.Value;
            if (value is Dictionary<string, object>)
            {
                value = GetObject((Dictionary<string, object>) value, prop.PropertyType); // <= This line
            }

            prop.SetValue(obj, value, null);
        }
        return obj;
    }

然后您可以创建一个执行转换的通用版本:

public static T GetObject<T>(this Dictionary<string, object> dict)
{
    return (T)GetObject(dict, typeof(T));
}

受@Dan Bryant 的回答启发,但在我的例子中,我的词典具有 ILists 属性,所以在这里我告诉你我是如何做到的。

public static T ToClass<T>(Dictionary<string, object> dict)
{
   return (T)ConverToClass(dict, typeof(T));
}

  
    private static object ConverToClass(Dictionary<string, object> dic, Type classToUse)
    {
        Type type = classToUse;
        var obj = Activator.CreateInstance(type);

        foreach (var item in dic)
        {
            var property = type.GetProperty(item.Key);
            if (property == null) continue;

            var value = item.Value;
            if (value is Dictionary<string, object> && !property.PropertyType.FullName.Contains("Generic.IList"))
            {
                property.SetValue(obj, ConverToClass((Dictionary<string, object>)(item.Value), property.PropertyType));
                continue;
            }
            if (property.PropertyType.FullName.Contains("Generic.IList"))
            {
                var subClassTouse = property.PropertyType.GetGenericArguments()[0];

                Type genericListType = typeof(List<>);
                Type concreteListType = genericListType.MakeGenericType(subClassTouse);
                var list = (IList)Activator.CreateInstance(concreteListType, new object[] { });

                var values = (Dictionary<string, object>)dic[item.Key];

                foreach (var itemClass in values)
                {
                    list.Add(ConverToClass((Dictionary<string, object>)itemClass.Value, subClassTouse));
                }
                property.SetValue(obj, list);
                continue;
            }
            property.SetValue(obj, item.Value);
        }

        return obj;
    }