Для этого может быть полезен метод Load, поэтому вы не перезаписываете ссылку, а устанавливаете все свойства старого объекта. Вот общий метод расширения, который я только что написал, который назначит все доступные для записи свойства, он очень грубый:
public static class ExtensionMethods
{
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);
}
}
}
}
}
После этого вы сможете звонить
item.Load(item.GetType(), currentDevice, true); //false for shallow loading
чтобы назначить все значения (если они являются свойствами).
Редактировать: Сделал метод рекурсивным, поэтому он будет вызывать Load
для свойств, которые не относятся к примитивному типу или типу значения (или строке). Вероятно, все еще плохо себя ведет в некоторых случаях.
Вы также можете добавить bool deep
к методу и контролировать, будет ли он загружен глубоко, если это потребуется. (Просто добавьте || !deep
к этому длинному выражению if)
Примечание. Конечно, вы также можете перезаписать ссылку на свой объект и использовать отражение, чтобы вызвать событие PropertyChanged для всех различных свойств, если хотите. В любом случае вам не нужно обрабатывать каждое свойство вручную.
Edit2: Поскольку PropertyInfo.GetValue
возвращает object
, мой предыдущий код не загружался рекурсивно, к сожалению, с этим вы должны явно передать Type, см. Ревизии для старой версии.
Edit3: Чтобы узнать, как сделать эту работу без ссылки на тип, см. Этот специальный вопрос , который я задал. Это, однако, не решает другие проблемы, такие как циклические ссылки и свойства, которые перечисляют объекты.