private static TTo CopyTo <TFrom, TTo>(this IEntityGraphShape shape, TFrom fromEntity, ITypeMapper typeMapper, IList visited) where TFrom : class where TTo : class { var toEntity = CopyFromTo <TFrom, TTo>(fromEntity, typeMapper); Debug.Assert(visited.Contains(fromEntity) == false); visited.Add(fromEntity); // Determine if provided shape is defined for fromEntity or for toEntity. var outEdges = shape.OutEdges(fromEntity).ToList(); if (!outEdges.Any()) { outEdges = shape.OutEdges(toEntity).ToList(); } var fromType = fromEntity.GetType(); var toType = toEntity.GetType(); foreach (var edge in outEdges) { var fromPropInfo = fromType.GetProperty(edge.Name); var toPropInfo = toType.GetProperty(edge.Name); if (fromPropInfo == null || toPropInfo == null) { continue; } var fromPropvalue = fromPropInfo.GetValue(fromEntity, null); if (fromPropvalue == null) { continue; } if (typeof(IEnumerable).IsAssignableFrom(fromPropInfo.PropertyType)) { var fromChildren = (IEnumerable)fromPropvalue; var toList = (IEnumerable)toPropInfo.GetValue(toEntity, null); // If the IEnumerable is null, lets try to allocate one if (toList == null) { var constr = toPropInfo.PropertyType.GetConstructor(new Type[] {}); toList = (IEnumerable)constr.Invoke(new object[] {}); toPropInfo.SetValue(toEntity, toList, null); } var addMethod = toPropInfo.PropertyType.GetMethod("Add"); foreach (var fromChild in fromChildren) { if (visited.Contains(fromChild) == false) { var toChild = shape.CopyTo <TFrom, TTo>((TFrom)fromChild, typeMapper, visited); addMethod.Invoke(toList, new object[] { toChild }); } } } else { var fromChild = (TFrom)fromPropvalue; if (visited.Contains(fromChild) == false) { var toChild = shape.CopyTo <TFrom, TTo>(fromChild, typeMapper, visited); toPropInfo.SetValue(toEntity, toChild, null); } } } return(toEntity); }