Я объединил некоторые части предыдущих ответов (спасибо этим авторам) и собрал простой статический класс с двумя методами, которые мы используем.
Да, это просто, нет, это не охватывает все сценарии, да, его можно расширить и сделать лучше, нет, это не идеально, да, это можно сделать более эффективным, нет, это не самая лучшая вещь с нарезанного хлеба, да, есть полнофункциональные надежные средства отображения объектов пакета nuget, которые лучше подходят для интенсивного использования и т. д. и т. д., yada yada - но, тем не менее, это работает для наших основных потребностей :)
И, конечно, он будет пытаться отобразить значения из любого объекта в любой объект, производный или нет (конечно, только общедоступные свойства, которые называются одинаковыми - остальные игнорируются).
ИСПОЛЬЗОВАНИЕ:
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
// creates new object of type "RealPerson" and assigns any matching property
// values from the puppet object
// (this method requires that "RealPerson" have a parameterless constructor )
RealPerson person = ObjectMapper.MapToNewObject<RealPerson>(puppet);
// OR
// create the person object on our own
// (so RealPerson can have any constructor type that it wants)
SesameStreetCharacter puppet = new SesameStreetCharacter() { Name = "Elmo", Age = 5 };
RealPerson person = new RealPerson("tall") {Name = "Steve"};
// maps and overwrites any matching property values from
// the puppet object to the person object so now our person's age will get set to 5 and
// the name "Steve" will get overwritten with "Elmo" in this example
ObjectMapper.MapToExistingObject(puppet, person);
СТАТИЧЕСКИЙ КЛАСС ПОЛЬЗОВАНИЯ:
public static class ObjectMapper
{
// the target object is created on the fly and the target type
// must have a parameterless constructor (either compiler-generated or explicit)
public static Ttarget MapToNewObject<Ttarget>(object sourceobject) where Ttarget : new()
{
// create an instance of the target class
Ttarget targetobject = (Ttarget)Activator.CreateInstance(typeof(Ttarget));
// map the source properties to the target object
MapToExistingObject(sourceobject, targetobject);
return targetobject;
}
// the target object is created beforehand and passed in
public static void MapToExistingObject(object sourceobject, object targetobject)
{
// get the list of properties available in source class
var sourceproperties = sourceobject.GetType().GetProperties().ToList();
// loop through source object properties
sourceproperties.ForEach(sourceproperty => {
var targetProp = targetobject.GetType().GetProperty(sourceproperty.Name);
// check whether that property is present in target class and is writeable
if (targetProp != null && targetProp.CanWrite)
{
// if present get the value and map it
var value = sourceobject.GetType().GetProperty(sourceproperty.Name).GetValue(sourceobject, null);
targetobject.GetType().GetProperty(sourceproperty.Name).SetValue(targetobject, value, null);
}
});
}
}