コード例 #1
0
        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("Не корректные данные трекера при клонировании объекта.");
            }
        }