예제 #1
0
 public void AddChildren(TrieNodeProperty child)
 {
     if (Children == null)
     {
         Children = new List <TrieNodeProperty>();
     }
     Children.Add(child);
 }
예제 #2
0
        /// <summary>
        /// Start the auto mapping process, this initializes memory and assigns value
        /// </summary>
        /// <param name="destination"></param>
        /// <param name="source"></param>
        /// <param name="propertyNode"></param>
        /// <param name="preserveExistingValue"></param>
        private static void StartAutoMappingProcess(TrieNodeProperty destinationNode,
                                                    TrieNodeProperty sourcePropertyNodes,
                                                    bool preserveExistingValue = false)
        {
            //Get the top most node in the tree
            TrieNodeProperty topMostNode = sourcePropertyNodes.GetTopMostRoot();

            //Map the source to the destination
            MapSourceToDestination(destinationNode, topMostNode);
        }
예제 #3
0
        public TrieNodeProperty GetTopMostRoot()
        {
            TrieNodeProperty topMostNode = this;

            while (!topMostNode.IsTopMostRoot())
            {
                topMostNode = topMostNode.Parent;
            }
            return(topMostNode);
        }
예제 #4
0
 public TrieNodeProperty(TrieNodeProperty parentProperty,
                         PropertyInfo currentProperty, object instance)
 {
     Parent   = parentProperty;
     Property = currentProperty;
     if (parentProperty != null)
     {
         parentProperty.AddChildren(this);
     }
     Instance         = instance;
     PreserveExisting = false;
 }
예제 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="property"></param>
        /// <param name="propertyMap"></param>
        private static void GetSubProperties(PropertyInfo property,
                                             TrieNodeProperty propertyMap)
        {
            //Create the object TRIE
            var propertyInstance = property.GetValue(propertyMap.Instance);

            propertyMap = new TrieNodeProperty(propertyMap, property, propertyInstance);
            //Map the Sub properties
            if (IsClass(property))
            {
                //Get all the properties that are public
                var subProperties = property.PropertyType
                                    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                    .Where(x => x.GetMethod != null && !x.GetMethod.IsPrivate &&
                                           x.SetMethod != null && !x.SetMethod.IsPrivate)
                                    .ToList();

                //Get the could of properties that are public
                var publicPropertiesCount = subProperties.Count;

                //Filter null properties
                subProperties = subProperties
                                .Where(x => x.GetValue(propertyInstance) != null)
                                .ToList();

                //Filter out value types with default value
                subProperties.ToList().ForEach(prop =>
                {
                    if (prop.PropertyType.IsValueType && object.Equals(prop.GetValue(propertyInstance), Activator.CreateInstance(prop.PropertyType)))
                    {
                        subProperties.Remove(prop);
                    }
                });

                //Get the new count of properties after filtering
                var filteredPublicPropertiesCount = subProperties.Count;

                //if the count does not match, then preserve existings
                if (filteredPublicPropertiesCount > 0 && publicPropertiesCount != filteredPublicPropertiesCount)
                {
                    propertyMap.PreserveExisting = true;
                }

                //Iterate the sub properties
                subProperties.ForEach(subproperty =>
                {
                    GetSubProperties(subproperty, propertyMap);
                });
            }
        }
예제 #6
0
        /// <summary>
        /// Get the properties of object map and index them.
        /// </summary>
        /// <param name="property">Property</param>
        /// <param name="parentPropertyName">Parent Property Name</param>
        /// <param name="propertyMappingIndex">Index of the object mapping</param>
        /// <param name="propertyMap">Property Node</param>
        /// <param name="propertyDepth">Current Depth of the scan</param>
        private static void GetProperties(PropertyInfo property,
                                          string parentPropertyName,
                                          Dictionary <Type, Dictionary <string, TrieNodeProperty> > propertyMappingIndex,
                                          TrieNodeProperty parentProperty)
        {
            string propertyName     = string.Empty;
            object propertyInstance = null;

            //Check the instance of parent property
            if (parentProperty.Instance != null)
            {
                propertyInstance = property.GetValue(parentProperty.Instance);
            }

            //Create the TRIE node
            parentProperty = new TrieNodeProperty(parentProperty, property, propertyInstance);

            propertyName = parentPropertyName.ToUpper();
            //Start indexing the property
            if (propertyMappingIndex.ContainsKey(property.PropertyType))
            {
                var propertiesList = propertyMappingIndex[property.PropertyType];
                propertiesList.Add(propertyName, parentProperty);
            }
            else
            {
                propertyMappingIndex.Add(property.PropertyType,
                                         new Dictionary <string, TrieNodeProperty>()
                {
                    { propertyName, parentProperty }
                });
            }
            //Map the Sub properties
            if (IsClass(property))
            {
                var subProperties = property.PropertyType
                                    .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                    .Where(x => x.GetMethod != null &&
                                           !x.GetMethod.IsPrivate &&
                                           x.SetMethod != null &&
                                           !x.SetMethod.IsPrivate)
                                    .ToList();
                subProperties.ForEach(subproperty =>
                {
                    propertyName = $"{parentPropertyName}.{subproperty.Name}";
                    GetProperties(subproperty, propertyName, propertyMappingIndex, parentProperty);
                });
            }
        }
예제 #7
0
        /// <summary>
        /// Go over the properties and map them to the target (destination)
        /// </summary>
        /// <param name="targetTrieNode">Target Trie node</param>
        /// <param name="sourcePropertyNode">Source Trie Node</param>
        private static void MapSourceToDestination(TrieNodeProperty targetTrieNode, TrieNodeProperty sourcePropertyNode)
        {
            if (IsClass(targetTrieNode.Property) &&
                targetTrieNode.Instance != null &&
                !sourcePropertyNode.HasChildren())
            {
                return;
            }

            //If the target Instance is null, that mean the property is null
            if (targetTrieNode.Instance == null)
            {
                //get the parent instance and assign the source directly to that.
                var parentInstance = targetTrieNode.GetParent().Instance;
                AssignSourceToDestination(parentInstance, parentInstance, sourcePropertyNode.Instance, targetTrieNode.Property);
                return;
            }

            if (sourcePropertyNode.HasChildren())
            {
                //Since the property has children, then we go deeper perform mapping on them
                //Iterate over each sub property and perform the mapping
                sourcePropertyNode.Children.ForEach(childProperty =>
                {
                    var targetChildProperty    = targetTrieNode.Instance.GetType().GetProperty(childProperty.Property.Name);
                    var targetPropertyInstance = targetChildProperty.GetValue(targetTrieNode.Instance);
                    if (targetPropertyInstance == null)
                    {
                        AssignSourceToDestination(targetTrieNode.Instance, targetTrieNode.Instance, childProperty.Instance, targetChildProperty);
                        return;
                    }
                    var targetNode = new TrieNodeProperty(targetTrieNode, targetChildProperty, targetPropertyInstance);
                    MapSourceToDestination(targetNode,
                                           childProperty);
                });
            }
            else
            {
                //Else - this means the property has no more child properties or you have reached the last property.
                //Map directly

                var targetChildProperty    = targetTrieNode.Property;
                var targetPropertyInstance = targetTrieNode.GetParent().Instance;

                AssignSourceToDestination(targetPropertyInstance, targetPropertyInstance, sourcePropertyNode.Instance, targetChildProperty);
            }
        }
예제 #8
0
        public static void Map(this object destination, object source,
                               string propertyName,
                               bool preserveExistingValue = false)
        {
            if (destination == null)
            {
                throw new NullArgumentException("The desination object (object to which the mapping has to happen) is null",
                                                $"{GetCurrentMethodName()}");
            }
            if (source == null)
            {
                throw new NullArgumentException("The source object (object from which the mapping has to happen) is null",
                                                $"{GetCurrentMethodName()}");
            }

            //Get the source and target object type
            var destinationType = destination.GetType();
            var sourceType      = source.GetType();

            if (object.Equals(destinationType, sourceType))
            {
                destination = source;
                return;
            }

            //If the destinaton type and source type are same and
            //destination is a list or array, then just assign source
            //Locate the correct property and instance on which the mapping has to happen
            TrieNodeProperty destinationNode = LocateSourcePropertyTypeInDestination(destination, source, propertyName);

            AutoInitialize(destinationNode);

            if (sourceType.IsGenericType || sourceType.IsArray)
            {
                var existingValue = destinationNode.Property.GetValue(destinationNode.GetParent().Instance);
                AssignSourceToDestination(destinationNode.GetParent().Instance,
                                          existingValue, source, destinationNode.Property);
                return;
            }

            //Property Trie - Make the top most root, doesn't have a value or a parent
            TrieNodeProperty sourcePropertyNode = LoadSourceObjectDictionary(source);

            //Start mapping, auto memory initializationa and value assigning
            StartAutoMappingProcess(destinationNode, sourcePropertyNode, preserveExistingValue);
        }
예제 #9
0
        /// <summary>
        /// Map the Object dictionary
        /// </summary>
        /// <param name="destination">Destination object</param>
        /// <param name="propertyMapping">Property mapping dictionary</param>
        private static TrieNodeProperty LoadSourceObjectDictionary(object source)
        {
            TrieNodeProperty propertyMappedTrie = new TrieNodeProperty(null, null, source);

            var publicProperties = source.GetType()
                                   .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                   .Where(x => x.GetMethod != null && !x.GetMethod.IsPrivate &&
                                          x.SetMethod != null && !x.SetMethod.IsPrivate)
                                   .ToList();


            var publicPropertiesCount = publicProperties.Count;

            publicProperties = publicProperties
                               .Where(x => x.GetValue(source) != null)
                               .ToList();

            //Filter out value types with default values
            publicProperties.ToList().ForEach(prop =>
            {
                if (prop.PropertyType.IsValueType && object.Equals(prop.GetValue(source), Activator.CreateInstance(prop.PropertyType)))
                {
                    publicProperties.Remove(prop);
                }
            });

            var filteredPublicPropertiesCount = publicProperties.Count;


            if (filteredPublicPropertiesCount > 0 && publicPropertiesCount != filteredPublicPropertiesCount)
            {
                propertyMappedTrie.PreserveExisting = true;
            }

            publicProperties.ForEach(property =>
            {
                GetSubProperties(property, propertyMappedTrie);
            });
            return(propertyMappedTrie);
        }
예제 #10
0
        /// <summary>
        /// Auto Initialize the parent Instances
        /// </summary>
        /// <param name="targetTrieNode"></param>
        private static void AutoInitialize(TrieNodeProperty targetTrieNode)
        {
            Stack <TrieNodeProperty> initializationOrder = new Stack <TrieNodeProperty>();

            //Create a stack order for intialization
            while (!targetTrieNode.IsTopMostRoot() && targetTrieNode.HasParent())
            {
                targetTrieNode = targetTrieNode.GetParent();
                var objectInstance = targetTrieNode.Instance;
                if (objectInstance == null)
                {
                    initializationOrder.Push(targetTrieNode);
                }
            }
            //Start creating initializing the objects
            while (initializationOrder.Count > 0)
            {
                var node           = initializationOrder.Pop();
                var objectInstance = CreateInstanceOfType(node.Property.PropertyType);
                node.SetInstance(objectInstance);
            }
        }
예제 #11
0
        /// <summary>
        /// Map the Object dictionary
        /// </summary>
        /// <param name="destination">Destination object</param>
        /// <param name="propertyMapping">Property mapping dictionary</param>
        private static Dictionary <Type, Dictionary <string, TrieNodeProperty> > LoadDestinationPropertyMap(object destination)
        {
            Dictionary <Type, Dictionary <string, TrieNodeProperty> > propertyMapping =
                new Dictionary <Type, Dictionary <string, TrieNodeProperty> >();

            TrieNodeProperty rootNode = new TrieNodeProperty(null, null, destination);
            var publicProperties      = destination.GetType()
                                        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                        .Where(x => x.GetMethod != null &&
                                               !x.GetMethod.IsPrivate &&
                                               x.SetMethod != null &&
                                               !x.SetMethod.IsPrivate)
                                        .ToList();

            publicProperties.ForEach(property =>
            {
                GetProperties(property,
                              property.Name,
                              propertyMapping,
                              rootNode);
            });

            return(propertyMapping);
        }