Начните с поиска, совместимы ли типы с
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;
}