private static void InnerClone(ITrackable fromClone, out ITrackable toClone, Dictionary <Type, PropertyInfo[]> propertyInfoDictionary) { // Предпологаем, что ITrackable fromClone может быть либо сущьностью, либо коллекцией сущьностей if (fromClone is BaseEntity from) // сущьность { var type = from.GetType(); PropertyInfo[] piList; #region Заполнение piList. Получение информации о свойствах PropertyInfo[] if (propertyInfoDictionary != null) { if (propertyInfoDictionary.ContainsKey(type)) { piList = propertyInfoDictionary[type].Where(x => x.CanRead && x.CanWrite).ToArray(); } else { piList = from.GetType().GetProperties().Where(x => x.CanRead && x.CanWrite).ToArray(); propertyInfoDictionary.Add(type, piList); } } else { piList = from.GetType().GetProperties().Where(x => x.CanRead && x.CanWrite).ToArray(); } #endregion toClone = fromClone.Clone() as ITrackable; var navigationProrertyList = piList.Where(x => typeof(BaseEntity).IsAssignableFrom(x.PropertyType)); var entityCollectionPi = piList.Where(x => x.PropertyType.Name == EntityStateMonitor.EntityCollectionPropertyTypeName); foreach (var pi in navigationProrertyList) { if (pi.GetValue(from) is BaseEntity newValue) { InnerClone(newValue, out ITrackable toCloneBaseEntity, propertyInfoDictionary); pi.SetValue(toClone, toCloneBaseEntity); } } foreach (var pi in entityCollectionPi) { if (pi.GetValue(from) is ITrackable newEntityCollectionValue) { InnerClone(newEntityCollectionValue, out ITrackable toCloneBaseEntity, propertyInfoDictionary); pi.SetValue(toClone, toCloneBaseEntity); } } } else if (fromClone is IEnumerable <BaseEntity> fromCloneEntityCollection) // коллекция сущьностей { toClone = Activator.CreateInstance(fromCloneEntityCollection.GetType()) as ITrackable; var list = new List <BaseEntity>(); foreach (var fromEntity in fromCloneEntityCollection) { InnerClone(fromEntity, out ITrackable toCloneBaseEntity, propertyInfoDictionary); if (toCloneBaseEntity is BaseEntity be) { list.Add(be); } } foreach (var x in list) { ((IEntityCollection)toClone)?.AddBaseEntity(x); } } else { throw new TrakerException("Не корректные данные трекера при клонировании объекта."); } }