Beispiel #1
0
        private static bool TryInvokeForeignFactory(object value, ObjectGraphFactoryMap factoryMap, out GraphNode root)
        {
            root = null;

            ObjectGraphFactory foreignFactory;

            if (value != null && factoryMap != null && factoryMap.TryGetValue(value.GetType(), out foreignFactory))
            {
                root = foreignFactory.CreateObjectGraph(value, factoryMap);
            }

            return(root != null);
        }
Beispiel #2
0
        private static GraphNodeTuple CreateGraphNode(object value, ObjectGraphFactoryMap factoryMap)
        {
            GraphNode node;
            bool      createdExternally = true;

            if (!TryInvokeForeignFactory(value, factoryMap, out node))
            {
                node = new GraphNode {
                    ObjectValue = value
                };
                createdExternally = false;
            }

            return(new GraphNodeTuple(node, createdExternally));
        }
Beispiel #3
0
        /// <summary>
        /// Given an object, get a list of tuples of the immediate child nodes.
        /// </summary>
        /// <param name="nodeData">The object whose child nodes need to be extracted</param>
        /// <param name="factoryMap">The factory map.</param>
        private Collection <GraphNodeTuple> GetChildNodes(object nodeData, ObjectGraphFactoryMap factoryMap)
        {
            var childNodes = new Collection <GraphNodeTuple>();

            // Extract and add properties
            foreach (var child in ExtractProperties(nodeData, factoryMap))
            {
                childNodes.Add(child);
            }

            // Extract and add IEnumerable content
            if (IsIEnumerable(nodeData))
            {
                foreach (var child in GetIEnumerableChildNodes(nodeData, factoryMap))
                {
                    childNodes.Add(child);
                }
            }

            return(childNodes);
        }
Beispiel #4
0
        private List <GraphNodeTuple> ExtractProperties(object nodeData, ObjectGraphFactoryMap factoryMap)
        {
            var childNodes = new List <GraphNodeTuple>();

            var properties = nodeData.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var property in properties)
            {
                object value = null;

                var parameters = property.GetIndexParameters();
                // Skip indexed properties and properties that cannot be read
                if (property.CanRead && parameters.Length == 0)
                {
                    try
                    {
                        value = property.GetValue(nodeData, null);
                    }
                    catch (Exception ex)
                    {
                        // If accessing the property threw an exception
                        // then make the type of exception as the child.
                        // Do we want to validate the entire exception object
                        // here ? - currently not doing to improve perf.
                        value = ex.GetType().ToString();
                    }

                    var tuple = CreateGraphNode(value, factoryMap);
                    // Set a child name in any case
                    tuple.Node.Name = property.Name;
                    childNodes.Add(tuple);
                }
            }
            ;

            return(childNodes);
        }
 /// <summary>
 /// Creates a graph for the given object.
 /// </summary>
 /// <param name="value">The object to convert.</param>
 /// <param name="factoryMap">
 /// The factory map is used when the currect factory encounters an object of a type
 /// it does not work with. In this case the factory should use the map to find a factory
 /// for that type and use it.
 /// </param>
 /// <returns>The root node of the created graph.</returns>
 public abstract GraphNode CreateObjectGraph(object value, ObjectGraphFactoryMap factoryMap = null);
Beispiel #6
0
        /// <summary>
        /// Creates a graph for the given object by extracting public properties.
        /// </summary>
        /// <param name="value">The object to convert.</param>
        /// <param name="factoryMap">
        /// If this parameter is not equal <see lang="null"/>, the map is used
        /// for each inner object to find out whether some other factory wants
        /// to process it.
        /// </param>
        /// <returns>The root node of the created graph.</returns>
        public override GraphNode CreateObjectGraph(object value, ObjectGraphFactoryMap factoryMap = null)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            // Queue of pending nodes
            Queue <GraphNode> pendingQueue = new Queue <GraphNode>();

            // Dictionary of < object hashcode, node > - to lookup already visited objects
            Dictionary <int, GraphNode> visitedObjects = new Dictionary <int, GraphNode>();

            GraphNode root;

            if (TryInvokeForeignFactory(value, factoryMap, out root))
            {
                // Everything is done for us
                return(root);
            }

            // Build the root ourselves and enqueue it
            root = new GraphNode()
            {
                Name        = "RootObject",
                ObjectValue = value,
            };

            pendingQueue.Enqueue(root);

            while (pendingQueue.Count != 0)
            {
                var currentNode = pendingQueue.Dequeue();
                var nodeData    = currentNode.ObjectValue;
                var nodeType    = currentNode.ObjectType;

                // If we have reached a leaf node -
                // no more processing is necessary
                if (IsLeafNode(nodeData, nodeType))
                {
                    continue;
                }

                // Handle loops by checking the visited objects
                if (visitedObjects.Keys.Contains(nodeData.GetHashCode()))
                {
                    // Caused by a cycle - we have already seen this node so
                    // use the existing node instead of creating a new one
                    var prebuiltNode = visitedObjects[nodeData.GetHashCode()];
                    currentNode.Children.Add(prebuiltNode);
                    continue;
                }
                else
                {
                    visitedObjects.Add(nodeData.GetHashCode(), currentNode);
                }

                // Extract and add child nodes for current object //
                var childNodes = GetChildNodes(nodeData, factoryMap);
                foreach (var childNode in childNodes)
                {
                    childNode.Node.Parent = currentNode;
                    currentNode.Children.Add(childNode.Node);

                    // If a node was created externally, we do not need to
                    // process it any longer. It is supposed to be fully built
                    if (!childNode.CreatedExternally)
                    {
                        pendingQueue.Enqueue(childNode.Node);
                    }
                }
            }

            return(root);
        }
Beispiel #7
0
        private static List <GraphNodeTuple> GetIEnumerableChildNodes(object nodeData, ObjectGraphFactoryMap factoryMap)
        {
            var childNodes = new List <GraphNodeTuple>();

            var enumerableData = nodeData as IEnumerable;
            var enumerator     = enumerableData.GetEnumerator();

            int count = 0;

            while (enumerator.MoveNext())
            {
                var tuple = CreateGraphNode(enumerator.Current, factoryMap);
                // Set a child name in any case
                tuple.Node.Name = "IEnumerable" + count++;
                childNodes.Add(tuple);
            }

            return(childNodes);
        }