Beispiel #1
0
        /// <summary>
        /// Removes the first instance of an element that has the given name.
        /// </summary>
        /// <param name="name">The name of the element to remove.</param>
        /// <returns>Returns true if the element was successfully removed. False if it did not exist within this template.</returns>
        public bool RemoveElementByName(string name)
        {
            if (_Children == null || _Children.Count < 1 || name == null || name.Length < 1)
            {
                return(false);
            }
            BaseElement elm = null;

            foreach (BaseElement element in _Children)
            {
                if (element.Name == name)
                {
                    elm = element;
                }
            }

            if (elm != null)
            {
                bool result = RemoveElement(elm);
                elm.Parent = null;
                return(result);
            }
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// This method performs reconciliation on all existing elements so that the old
        /// template matches this one.
        /// Then it adds new elements to the old template. Finally, it tries to reconcile
        /// elements that have been fundamentally changed in the new template. Failing that,
        /// elements that cannot be resolved are simply removed until the old template
        /// matches the new one.
        /// </summary>
        /// <param name="oldTemplate"></param>
        /// <returns></returns>
        public bool ReconcileElementProperties(BaseElement oldTemplate)
        {
            if (!this.Guid.Equals(oldTemplate.Guid))
            {
                return(false);
            }
            Type sourceType = this.GetType();
            Type oldType    = this.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 <ShallowElementCloneAttribute>(true) != null)
                {
                    targetProperty.SetValue(oldTemplate, property.GetValue(this, null), null);
                }
            }

            List <IElement> newElements = new List <IElement>();

            //now we are going to loop through the list of elements within the template
            //and try to reconcile their properties.
            foreach (IElement element in _Children)
            {
                bool notCopied = true;

                //yucky inner-loop that loop that looks
                //for the matching element within the old template.
                foreach (BaseElement oldElement in oldTemplate.Children)
                {
                    //this automatically checks the Guids to see if
                    //they are the matching element. No worries here.
                    //It will simply return if there is not a match...
                    //or you know... they generated the same Guid somehow ;)
                    if (element.ReconcileElementProperties(oldElement))
                    {
                        notCopied = false;
                        break;
                    }
                }

                //if the element couldn't be found in the old template, we'll need to
                //add it to a list that will be appened later
                if (notCopied)
                {
                    newElements.Add(element);
                }
            }

            //now something tricky. We need to add elements to
            //the old template to match the new one.
            foreach (IElement append in newElements)
            {
                oldTemplate.AddElement(append.GetShallowClone());
            }

            return(false);
        }
Beispiel #3
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);
        }
Beispiel #4
0
 /// <summary>
 /// Adds a new element to the template.
 /// </summary>
 /// <param name="element"></param>
 public virtual void AddElement(BaseElement element)
 {
     InitElementList();
     _Children.Add(ConvertElement(element));
     element.Parent = this;
 }
Beispiel #5
0
 /// <summary>
 /// This default implementation in fact does not peform a deep copy. It is a stand-in
 /// shallow copy using reflection of the object's proeprties. For a proper deep-copy,
 /// override this method and implement according to the Element's _Content datatype.
 /// </summary>
 /// <param name="sourceProp"></param>
 /// <param name="sourceElm"></param>
 /// <param name="destProp"></param>
 /// <param name="destElm"></param>
 protected virtual void DeepClone(PropertyInfo sourceProp, BaseElement sourceElm, PropertyInfo destProp, BaseElement destElm)
 {
     destProp.SetValue(destElm, sourceProp.GetValue(sourceElm, null), null);
 }