Пример #1
0
        /// <summary>
        /// Updates a give template to reflect this one. Elements that
        /// share a name and datatype are transferred to the best ability.
        /// Elements that are not present in this one are removed.
        /// </summary>
        /// <param name="template"></param>
        public bool ReconcileElementProperties(BaseElement oldElement, bool reconcileOverrides = false)
        {
            //This assumes we already have an an element that matches this element's Guid
            if (!this.Guid.Equals(oldElement.Guid))
            {
                return(false);
            }
            Type sourceType = this.GetType();
            Type oldType    = oldElement.GetType();

            //first, let's do the easy stuff and update existing properties for both templates
            foreach (var property in sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var targetProperty = oldType.GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance);
                if (targetProperty != null &&
                    targetProperty.CanWrite &&
                    targetProperty.GetCustomAttribute <ReconcilableProp>(true) != null &&
                    property.GetCustomAttribute <ReconcilableProp>(true) != null)
                {
                    if (targetProperty.GetCustomAttribute <ReconcilableProp>(true).Override == reconcileOverrides)
                    {
                        //edit property to reflect template changes
                        targetProperty.SetValue(oldElement, property.GetValue(this, null), null);
                    }
                }
            }


            //TODO: We must have an 'intelligent' mechinism here that can attempt to compare
            //properties of different Guids but the same ID. If IDs match, it tries to convert
            //the data from the old element format to the new one. Otherwise it must delete that data.


            //TODO: We must remove elements from the card that were removed from the master template
            //This will be dangerous and requires mitigation from the above mechanism as well as plenty
            //of warnings to the user about what they are doing.


            //now we must compare each child in this element with each child
            //of the other element. If one of them matches, we need to reconcile them
            foreach (BaseElement child in _Children)
            {
                //update: this will automagically compare Guids within the call now
                foreach (BaseElement targetChild in oldElement.Children)
                {
                    child.ReconcileElementProperties(targetChild);
                }
            }

            return(true);
        }
Пример #2
0
        /// <summary>
        /// Copies this element to another element using shallow copying
        /// of all basic properties. Child elements however, are still
        /// deeply copied using recursion. This will not handle indexed properties.
        /// </summary>
        /// <returns></returns>
        public BaseElement GetShallowClone()
        {
            BaseElement dest = Activator.CreateInstance(this.GetType()) as BaseElement;

            if (dest == null)
            {
                return(null);
            }
            Type sourceType = this.GetType();
            Type targetType = dest.GetType();

            //copy all values of all elements marked with a clone attribute
            foreach (var property in sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                var targetProperty = targetType.GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance);
                if (targetProperty != null &&
                    targetProperty.CanWrite &&
                    targetProperty.PropertyType.IsAssignableFrom(property.PropertyType) &&
                    targetProperty.GetCustomAttribute <ShallowElementCloneAttribute>(true) != null &&
                    property.GetCustomAttribute <ShallowElementCloneAttribute>(true) != null)
                {
                    targetProperty.SetValue(dest, property.GetValue(this, null), null);
                }
                else if (targetProperty != null &&
                         targetProperty.CanWrite &&
                         targetProperty.PropertyType.IsAssignableFrom(property.PropertyType) &&
                         targetProperty.GetCustomAttribute <DeepElementCloneAttribute>(true) != null &&
                         property.GetCustomAttribute <DeepElementCloneAttribute>(true) != null)
                {
                    try
                    {
                        targetProperty.SetValue(dest, Utils.ObjectHelper.Clone(property.GetValue(this, null)), null);
                    }
                    catch (ArgumentException e)
                    {
                        MessageBox.Show("Failed to deep copy the property '" + property.Name + "' of the element '" + this._Name + "'.\n" + e.Message);
                    }
                }
                else if (
                    targetProperty != null &&
                    targetProperty.CanWrite &&
                    targetProperty.PropertyType.IsAssignableFrom(property.PropertyType) &&
                    targetProperty.GetCustomAttribute <ContentElementCloneAttribute>(true) != null &&
                    property.GetCustomAttribute <ContentElementCloneAttribute>(true) != null)
                {
                    this.DeepClone(property, this, targetProperty, dest);
                }
            }


            //manually copy InstanceProperties
            //We need to generate the InstanceEditProperty controls and bind them here.
            dest.BindInstanceEditProps();
            //TODO: set default values to binding property

            //now deep shallow-copy of the children
            foreach (BaseElement child in _Children)
            {
                dest.Children.Add(child.GetShallowClone());
            }

            //we use reflection to get the private Guid value.
            //We do this in an effort to avoid letting overriding
            //classes mess with the Guid
            FieldInfo sourceGuid = sourceType.GetField("_Guid", BindingFlags.NonPublic | BindingFlags.Instance);
            FieldInfo destGuid   = targetType.GetField("_Guid", BindingFlags.NonPublic | BindingFlags.Instance);

            destGuid.SetValue(dest, sourceGuid.GetValue(this));
            return(dest);
        }