Для вопроса SO я совсем недавно написал общий метод расширения, который должен загружать объект из другого, то есть назначать все свойства источника для цели и делать это рекурсивно, если свойство является ссылкой -тип. Я довольно далеко использовал рефлексию, но столкнулся с проблемой, когда дело дошло до типов свойств, которые являются ссылочными, вот мой первый подход:
Первый подход:
public static void Load<T>(this T target, T source, bool deep)
{
foreach (PropertyInfo property in typeof(T).GetProperties())
{
if (property.CanWrite && property.CanRead)
{
if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
{
property.SetValue(target, property.GetValue(source, null), null);
}
else
{
property.GetValue(target, null).Load(property.GetValue(source, null), deep);
}
}
}
}
Проблема здесь в том, что PropertyInfo.GetValue
возвращает объект, впоследствии T
будет равняться object
в рекурсивном вызове, и я больше не могу получить свойства, которые на самом деле имеет объект.
Я придумал обходной путь, который требует от вас явной передачи Типа, что довольно избыточно, поскольку теоретически можно обойтись без:
public static void Load<T>(this T target, Type type, T source, bool deep)
{
foreach (PropertyInfo property in type.GetProperties())
{
if (property.CanWrite && property.CanRead)
{
if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
{
property.SetValue(target, property.GetValue(source, null), null);
}
else
{
object targetPropertyReference = property.GetValue(target, null);
targetPropertyReference.Load(targetPropertyReference.GetType(), property.GetValue(source, null), deep);
}
}
}
}
Я также пытался использовать dynamic targetPropertyReference
, но затем я получаю исключение времени выполнения, что метод Load
не может быть найден, это бесит.
Кроме этого Convert.ChangeType
также легко возвращает кровавый object
, и я не могу иначе привести объект к тому, что он есть. Конечно, я искал ответ на этот вопрос в сети, но мне пока не удалось.