Как отобразить родительский класс, включая их вложенные дети
Если у меня есть два класса, как это:
1-ParentViewModel:
public class ParentViewModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public IList<ChildViewModel> Children { get; set; }
}
2- ChildViewModel
public class ChildViewModel
{
public Guid? Id { get; set; }
public string Name { get; set; }
public Guid? ParentViewModelId { get; set; }
}
И у меня есть две доменные модели, родительский эквивалент содержит:Icollection<Child>
вместо IList<ChildViewModel>
Я хочу сопоставить модель родительского представления с родительским доменом (включая сопоставление дочерних элементов) и наоборот с домена для просмотра модели, включающей вложенные дочерние элементы?
1 ответ
Вы всегда можете просто вручную / утомительно отобразить свойства, но, если вы хотите более общее решение, вы можете использовать отражение для сопоставления свойств по имени и обработки специального случая для коллекций.
* Примечания: 1. Это не удастся для свойств, которые являются типами коллекции интерфейсов, но вы можете немного изменить код, чтобы справиться с этим. 2. Обработка ошибок не была добавлена. 3. Попытка сопоставить свойства по имени, поэтому класс домена и класс модели представления должны иметь одинаковые имена проп. 4. Он пропустит свойства, которые он не находит в целевом классе
public class ObjectMapper
{
public void MapObject(object source, object destination)
{
var srcType = source.GetType();//get source type
var srcProps = srcType.GetProperties();//get src props, supply appropriate binding flags
var destType = destination.GetType();//get dest type
var destProps = destType.GetProperties();//get dest props, supply appropriate binding flags
foreach (var prop in srcProps)
{
//find corresponding prop on dest obj
var destProp = destProps.FirstOrDefault(p => p.Name == prop.Name);
//only map if found on dest obj
if (destProp != null)
{
//get src value
var srcVal = prop.GetValue(source);
//get src prop type
var propType = prop.PropertyType;
//get dest prop type
var destPropType = destProp.PropertyType;
//special case for collections
if (typeof(IList).IsAssignableFrom(propType))
{
//instantiate dest collection
var newCollection = (IList)Activator.CreateInstance(destPropType);
//get source collection
var collection = (IList)srcVal;
//get dest collection element type
var elementType = destPropType.GetGenericArguments().FirstOrDefault();
//iterate collection
foreach (var element in collection)
{
//instantiate element type
var tempElement = Activator.CreateInstance(elementType);
//call map object on each element
MapObject(source: element, destination: tempElement);
//add mapped object to new collection
newCollection.Add(tempElement);
}
//set dest object prop to collection
destProp.SetValue(destination, newCollection);
}
else
{
destProp.SetValue(destination, srcVal);
}
}
}
}
}