Exemple #1
0
        /// <summary>
        /// 复制目标对象的所有字段。
        /// 子类重写此方法额外做以下几件事:
        /// 1. 如果有自定义字段,请在此方法中进行值拷贝。
        /// 2. 如果有延迟加载的外键引用对象 ILazyEntityRef,请调用它的 Clone 方法进行拷贝。
        /// 3. 如果使用了快速字段 FastField 来进行属性的缓存,请在基类完成 Clone 后,调用本类的 ResetFastField 方法来清空缓存。
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="options">The options.</param>
        /// <exception cref="System.ArgumentNullException">source
        /// or
        /// options</exception>
        protected virtual void CloneCore(Entity source, CloneOptions options)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            var grabChildren  = options.HasAction(CloneActions.GrabChildren);
            var childrenRecur = options.HasAction(CloneActions.ChildrenRecur);
            var copyId        = options.HasAction(CloneActions.IdProperty);

            var ingoreList = options.RetrieveIgnoreListOnce();

            //如果需要拷贝id,则应该先拷贝id,并立刻清空id的缓存。
            //注意:
            //由于 IdProperty 在 AllProperties 中的位置并不是第一个。所以会出现拷贝其它属性时,再次访问本ID导致缓存重建。
            //所以这里需要单独对 Id 进行一次拷贝。
            if (copyId)
            {
                this.CopyProperty(source, IdProperty, options);
            }

            //复制目标对象的所有托管属性。
            var allProperties = this.PropertiesContainer.GetAvailableProperties();

            for (int i = 0, c = allProperties.Count; i < c; i++)
            {
                var property = allProperties[i];
                if (property.IsReadOnly)
                {
                    continue;
                }
                //var propertyMeta = property.GetMeta(this) as IPropertyMetadata;

                //过滤一些不需要拷贝的属性
                if (property == IdProperty && !copyId)
                {
                    continue;
                }
                if (ingoreList != null && ingoreList.Contains(property))
                {
                    continue;
                }
                //已经更改了GetLazyChildren方法,不再考虑null值的拷贝。
                ////如果目标不存在这个值时,不需要也不能进行拷贝,否则会为懒加载属性的加载null值。
                //if (!target.FieldManager.FieldExists(propertyInfo)) continue;

                if (property is IListProperty)
                {
                    var listProperty = property as IListProperty;
                    if (childrenRecur)
                    {
                        var sourceList = source.GetLazyList(listProperty);
                        var targetList = this.GetLazyList(listProperty);
                        targetList.Clone(sourceList, options);

                        var isComposition = targetList.HasManyType == HasManyType.Composition;
                        if (isComposition)
                        {
                            targetList.SetParentEntity(this);
                        }
                    }
                    else if (grabChildren)
                    {
                        var children = source.GetProperty(property) as EntityList;
                        this.LoadProperty(property, children);
                        if (children == null)
                        {
                            return;
                        }

                        var isComposition = children.HasManyType == HasManyType.Composition;
                        if (isComposition)
                        {
                            children.SetParentEntity(this);
                        }
                    }
                }
                else
                {
                    this.CopyProperty(source, property, options);
                }
            }

            options.NotifyCloned(source, this);

            if (this.SupportTree)
            {
                this.OnTreeItemCloned(source, options);
            }
        }
Exemple #2
0
 /// <summary>
 /// 使用指定的复制条件来复制源对象的值。
 /// </summary>
 /// <param name="source"></param>
 /// <param name="options"></param>
 public void Clone(Entity source, CloneOptions options)
 {
     this.CloneCore(source, options);
 }
Exemple #3
0
        /// <summary>
        /// 复制指定的属性值。
        /// </summary>
        /// <param name="source">从这个对象拷贝</param>
        /// <param name="property">拷贝这个属性</param>
        /// <param name="options">The options.</param>
        protected virtual void CopyProperty(Entity source, IManagedProperty property, CloneOptions options)
        {
            var value = source.GetProperty(property);

            if (options.Method == CloneValueMethod.LoadProperty)
            {
                this.LoadProperty(property, value);
            }
            else
            {
                this.SetProperty(property, value);
            }
        }
Exemple #4
0
 /// <summary>
 /// 使用 <see cref="CloneOptions.NewSingleEntity"/> 来复制目标对象。
 /// </summary>
 /// <param name="source"></param>
 public void Clone(Entity source)
 {
     this.CloneCore(source, CloneOptions.NewSingleEntity());
 }
Exemple #5
0
        /// <summary>
        /// 复制目标对象的所有字段。
        /// 子类重写此方法额外做以下几件事:
        /// 1. 如果有自定义字段,请在此方法中进行值拷贝。
        /// 2. 如果有延迟加载的外键引用对象 ILazyEntityRef,请调用它的 Clone 方法进行拷贝。
        /// 3. 如果使用了快速字段 FastField 来进行属性的缓存,请在基类完成 Clone 后,调用本类的 ResetFastField 方法来清空缓存。
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="options">The options.</param>
        /// <exception cref="System.ArgumentNullException">source
        /// or
        /// options</exception>
        protected virtual void CloneCore(Entity source, CloneOptions options)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            //准备一些控制变量
            var grabChildren   = options.HasAction(CloneActions.GrabChildren);
            var childrenRecur  = options.HasAction(CloneActions.ChildrenRecur);
            var copyId         = options.HasAction(CloneActions.IdProperty);
            var cloneParentRef = options.HasAction(CloneActions.ParentRefEntity);
            var cloneRef       = options.HasAction(CloneActions.RefEntities);
            var ingoreList     = options.RetrieveIgnoreList(false);

            //如果需要拷贝id,则应该先拷贝id。否则后续在拷贝组合子时,可能访问不当前实体的 Id。
            if (copyId)
            {
                this.CopyProperty(source, IdProperty, options);
            }

            //复制目标对象的所有托管属性。
            var allProperties = this.PropertiesContainer.GetAvailableProperties();

            for (int i = 0, c = allProperties.Count; i < c; i++)
            {
                var property = allProperties[i];
                if (property.IsReadOnly)
                {
                    continue;
                }

                //过滤一些不需要拷贝的属性
                if (property == IdProperty)
                {
                    continue;                        //Id 已经提前处理过了。
                }
                if (ingoreList != null && ingoreList.Contains(property))
                {
                    continue;
                }

                if (property is IListProperty)
                {
                    if (childrenRecur || grabChildren)
                    {
                        if (!source.FieldExists(property))
                        {
                            this.ResetProperty(property);
                        }
                        else
                        {
                            var listProperty = property as IListProperty;
                            var sourceList   = source.GetProperty(listProperty) as EntityList;

                            EntityList children = null;
                            if (childrenRecur)
                            {
                                children = this.LoadLazyList(listProperty, true);
                                children.Clone(sourceList, options);//内部 Add 时会调用 children.SetParentEntity(this);
                            }
                            else//grabChildren
                            {
                                children = sourceList;
                                this.LoadProperty(property, children);//Load 时会调用 children.SetParentEntity(this);
                            }
                        }
                    }
                }
                else if (property is IRefEntityProperty)
                {
                    bool copyEntity = (property as IRefEntityProperty).ReferenceType == ReferenceType.Parent ? cloneParentRef : cloneRef;
                    if (copyEntity && source.GetProperty(property) != null)
                    {
                        this.CopyProperty(source, property, options);
                    }
                }
                else
                {
                    this.CopyProperty(source, property, options);
                }
            }

            var supportTree = this.SupportTree;

            if (supportTree)
            {
                this.CloneTreeRelations(source, options, childrenRecur, grabChildren, cloneParentRef);
            }

            //如果 Id 值没有拷贝,那么组合子实体中的 PId 需要重新整理。
            //由于这种场景下没有拷贝 Id,又需要重新整理 PId 和 TreePId,所以可以使用 SetProperty 方法来变更实体的状态。
            if (!copyId && (childrenRecur || grabChildren))
            {
                foreach (var child in this.GetLoadedChildren())
                {
                    var list = child.Value as EntityList;
                    if (list != null)
                    {
                        list.SetParentEntity(this);
                    }
                }

                if (supportTree)
                {
                    (this as ITreeComponent).EachNode(e =>
                    {
                        e.SyncTreeChildrenPId();
                        return(false);
                    });
                }
            }

            //如果是新构建的实体,持久化状态也完全拷贝。(如果 Id 没有被拷贝,说明是只拷贝值,那么不需要变更新实体的状态)
            if (this.IsNew && copyId && !source.IsNew)
            {
                this.PersistenceStatus = source.PersistenceStatus;
            }

            options.NotifyCloned(source, this);
        }