将 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;
}
如何将字典递归地转换为 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;
}