我有一种方法,我喜欢使用反射机制执行一些不同的转换。
private static T GetObject<T>(Dictionary<string, object> dict)
{
Type type = typeof(T);
var obj = Activator.CreateInstance(type);
foreach (var kv in dict)
{
var p = type.GetProperty(kv.Key);
Type t = p.PropertyType;
Type t2 = kv.Value.GetType();
if (t == t2)
{
p.SetValue(obj, kv.Value);
}
else if (!IsPrimitive(p.PropertyType))
{
p.SetValue(obj, GetObject<class of p>((Dictionary<string, object>) kv.Value)); //???
}
else
{
p.SetValue(obj, (primitive)(kv.Value)); //???
}
}
return (T)obj;
}
已编辑
我有一个字典,我想将它转换为自定义类,字典中的每个键都是一个属性,每个字典值都是该属性的值。问题出现在两种情况下,当类属性类型和字典值类型都是基元但它们具有不同的类型(例如,属性是 int 但字典值是 long)时,第二个问题出现在属性值是另一个自定义类并且在这种情况下字典值总是另一个字典
如何动态检测必要的转换?
最佳答案
首先查看类型是否与赋值兼容
if (t.IsAssignableFrom(t2))
否则转换为
object converted = Convert.ChangeType(kv.Value, t);
这应该可以处理很多情况。
由于您必须使用仅在运行时知道的类型递归调用该方法,因此最好使用 GetObject
的非泛型重载版本。原始方法只调用非泛型
private static T GetObject<T>(Dictionary<string, object> dict)
where T : class, new() // Suggested by Brett Caswell.
{
return (T)GetObject(dict, typeof(T));
}
请注意,泛型类型参数总是在编译时解析。由于您必须在运行时动态解析类型,因此它们在这里更像是一个障碍。您可以使用反射构造通用方法调用,但我看不出这样做有什么好处。它很复杂而且类型不安全。类型安全只能由编译器强制执行。
private static object GetObject(Dictionary<string, object> dict, Type objectType)
{
object obj = Activator.CreateInstance(objectType);
foreach (var kv in dict) {
PropertyInfo prop = objectType.GetProperty(kv.Key);
Type propType = prop.PropertyType;
object value = kv.Value;
if (value == null) {
if (propType.IsValueType) { // Get default value of type.
value = Activator.CreateInstance(propType);
}
} else if (value is Dictionary<string, object> nestedDict) {
value = GetObject(nestedDict, propType);
} else if (!propType.IsAssignableFrom(value.GetType())) {
value = Convert.ChangeType(value, propType);
}
prop.SetValue(obj, value);
}
return obj;
}
关于C#如何动态检测泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54055607/