Beispiel #1
0
        /// <summary>
        /// Set the <see cref="TargetNode"/> and <see cref="TargetGuid"/> of the targeted object by retrieving it from or creating it to the given <see cref="NodeContainer"/>.
        /// </summary>
        /// <param name="nodeContainer">The <see cref="NodeContainer"/> used to retrieve or create the target node.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        internal IGraphNode SetTarget(NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            if (nodeContainer == null)
            {
                throw new ArgumentNullException(nameof(nodeContainer));
            }
            IGraphNode targetNode = nodeContainer.GetOrCreateNode(ObjectValue, nodeFactory);

            if (targetNode != null)
            {
                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value))
                {
                    throw new InvalidOperationException(@"The type of the retrieved node content does not match the type of this reference");
                }

                if (TargetNode != null || TargetGuid != Guid.Empty)
                {
                    throw new InvalidOperationException("TargetNode has already been set.");
                }
                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value))
                {
                    throw new InvalidOperationException("TargetNode type does not match the reference type.");
                }
                TargetNode = targetNode;
                TargetGuid = targetNode.Guid;
            }
            return(targetNode);
        }
Beispiel #2
0
        /// <summary>
        /// Creates a graph node.
        /// </summary>
        /// <param name="rootObject">The root object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>A new graph node representing the given root object.</returns>
        private IGraphNode CreateNode(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (rootObject == null)
            {
                throw new ArgumentNullException(nameof(rootObject));
            }

            Guid guid = Guid.NewGuid();

            // Retrieve results
            if (guidContainer != null && !rootObject.GetType().IsValueType)
            {
                guid = guidContainer.GetOrCreateGuid(rootObject);
            }

            var result = (GraphNode)NodeBuilder.Build(rootObject, guid, nodeFactory);

            if (result != null)
            {
                // Register the factory used to create this node.
                factoriesByNode.Add(result, nodeFactory);
                // Register reference objects
                nodesByGuid.Add(result.Guid, result);
                // Create or update nodes of referenced objects
                UpdateReferences(result);
            }

            return(result);
        }
Beispiel #3
0
 /// <inheritdoc/>
 public void OverrideNodeFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         defaultNodeFactory = nodeFactory;
     }
 }
Beispiel #4
0
 /// <inheritdoc/>
 public void OverrideNodeFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         defaultNodeFactory = nodeFactory;
     }
 }
Beispiel #5
0
        /// <summary>
        /// Set the <see cref="TargetNode"/> and <see cref="TargetGuid"/> of the targeted object by retrieving it from or creating it to the given <see cref="NodeContainer"/>.
        /// </summary>
        /// <param name="nodeContainer">The <see cref="NodeContainer"/> used to retrieve or create the target node.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        internal IGraphNode SetTarget(NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            if (nodeContainer == null)
            {
                throw new ArgumentNullException(nameof(nodeContainer));
            }
            IGraphNode targetNode = nodeContainer.GetOrCreateNodeInternal(ObjectValue, nodeFactory);

            if (targetNode != null)
            {
                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value))
                {
                    throw new InvalidOperationException(@"The type of the retrieved node content does not match the type of this reference");
                }

                // TODO: Disabled this exception which is triggered when a circular reference is made. This will be properly fixed when we'll get rid of the ShouldProcessReference mechanism.
                //if (TargetNode != null || TargetGuid != Guid.Empty)
                //    throw new InvalidOperationException("TargetNode has already been set.");

                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value))
                {
                    throw new InvalidOperationException("TargetNode type does not match the reference type.");
                }

                TargetNode = targetNode;
                TargetGuid = targetNode.Guid;
            }
            return(targetNode);
        }
Beispiel #6
0
 /// <summary>
 /// Registers the default factory to use to create <see cref="IGraphNode"/> instances.
 /// </summary>
 /// <param name="nodeFactory">The factory to register.</param>
 public void RegisterDefaultFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         nodeFactories[new NodeFactoryId(Guid.Empty)] = nodeFactory;
         defaultNodeFactory = nodeFactory;
     }
 }
Beispiel #7
0
 /// <summary>
 /// Registers the default factory to use to create <see cref="IGraphNode"/> instances.
 /// </summary>
 /// <param name="nodeFactory">The factory to register.</param>
 public void RegisterDefaultFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         nodeFactories[new NodeFactoryId(Guid.Empty)] = nodeFactory;
         defaultNodeFactory = nodeFactory;
     }
 }
Beispiel #8
0
 public NodeFactoryId RegisterFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         var id = new NodeFactoryId(Guid.NewGuid());
         nodeFactories.Add(id, nodeFactory);
         return id;
     }
 }
Beispiel #9
0
 public NodeFactoryId RegisterFactory(NodeFactoryDelegate nodeFactory)
 {
     lock (lockObject)
     {
         var id = new NodeFactoryId(Guid.NewGuid());
         nodeFactories.Add(id, nodeFactory);
         return(id);
     }
 }
Beispiel #10
0
 /// <inheritdoc/>
 public IGraphNode Build(object obj, Guid guid, NodeFactoryDelegate nodeFactory)
 {
     if (obj == null) throw new ArgumentNullException(nameof(obj));
     if (nodeFactory == null) throw new ArgumentNullException(nameof(nodeFactory));
     Reset();
     rootGuid = guid;
     var typeDescriptor = TypeDescriptorFactory.Find(obj.GetType());
     currentNodeFactory = nodeFactory;
     VisitObject(obj, typeDescriptor as ObjectDescriptor, true);
     currentNodeFactory = null;
     return rootNode;
 }
 internal void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory, Index index)
 {
     var objectValue = ownerNode.Content.Retrieve(index);
     if (TargetNode?.Content.Value != objectValue)
     {
         // This call will recursively update the references.
         var target = SetTarget(objectValue, nodeContainer, nodeFactory);
         if (target != null)
         {
             var ownerContent = (ContentBase)ownerNode.Content;
             var boxedContent = target.Content as BoxedContent;
             boxedContent?.SetOwnerContent(ownerContent, index);
         }
     }
     // This reference is not orphan anymore.
     orphanObject = null;
 }
Beispiel #12
0
        /// <summary>
        /// Set the <see cref="TargetNode"/> and <see cref="TargetGuid"/> of the targeted object by retrieving it from or creating it to the given <see cref="NodeContainer"/>.
        /// </summary>
        /// <param name="nodeContainer">The <see cref="NodeContainer"/> used to retrieve or create the target node.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        internal IGraphNode SetTarget(NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            if (nodeContainer == null) throw new ArgumentNullException(nameof(nodeContainer));
            IGraphNode targetNode = nodeContainer.GetOrCreateNode(ObjectValue, nodeFactory);
            if (targetNode != null)
            {
                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value)) throw new InvalidOperationException(@"The type of the retrieved node content does not match the type of this reference");

                if (TargetNode != null || TargetGuid != Guid.Empty)
                    throw new InvalidOperationException("TargetNode has already been set.");
                if (targetNode.Content.Value != null && !Type.IsInstanceOfType(targetNode.Content.Value))
                    throw new InvalidOperationException("TargetNode type does not match the reference type.");
                TargetNode = targetNode;
                TargetGuid = targetNode.Guid;
            }
            return targetNode;
        }
Beispiel #13
0
        internal void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory, Index index)
        {
            var objectValue = ownerNode.Content.Retrieve(index);

            if (TargetNode?.Content.Value != objectValue)
            {
                // This call will recursively update the references.
                var target = SetTarget(objectValue, nodeContainer, nodeFactory);
                if (target != null)
                {
                    var ownerContent = (ContentBase)ownerNode.Content;
                    var boxedContent = target.Content as BoxedContent;
                    boxedContent?.SetOwnerContent(ownerContent, index);
                }
            }
            // This reference is not orphan anymore.
            orphanObject = null;
        }
Beispiel #14
0
        public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            var newObjectValue = ownerNode.Content.Value;

            if (!(newObjectValue is IEnumerable))
            {
                throw new ArgumentException(@"The object is not an IEnumerable", nameof(newObjectValue));
            }

            ObjectValue = newObjectValue;

            // First, let's build a new list of uninitialized references
            var newReferences = new List <ObjectReference>(IsDictionary
                ? ((IEnumerable)ObjectValue).Cast <object>().Select(x => (ObjectReference)Reference.CreateReference(GetValue(x), elementType, GetKey(x)))
                : ((IEnumerable)ObjectValue).Cast <object>().Select((x, i) => (ObjectReference)Reference.CreateReference(x, elementType, new Index(i))));

            // The reference need to be updated if it has never been initialized, if the number of items is different, or if any index or any value is different.
            var needUpdate = references == null || newReferences.Count != references.Count || newReferences.Zip(references).Any(x => !x.Item1.Index.Equals(x.Item2.Index) || !Equals(x.Item1.ObjectValue, x.Item2.ObjectValue));

            if (needUpdate)
            {
                // We create a dictionary that maps values of the old list of references to their corresponding target node.
                var dictionary = references?.Where(x => x.ObjectValue != null && !(x.TargetNode?.Content is BoxedContent)).ToDictionary(x => x.ObjectValue) ?? new Dictionary <object, ObjectReference>();
                foreach (var newReference in newReferences)
                {
                    if (newReference.ObjectValue != null)
                    {
                        ObjectReference oldReference;
                        if (dictionary.TryGetValue(newReference.ObjectValue, out oldReference))
                        {
                            // If this value was already present in the old list of reference, just use the same target node in the new list.
                            newReference.SetTarget(oldReference.TargetNode);
                        }
                        else
                        {
                            // Otherwise, do a full update that will properly initialize the new reference.
                            newReference.Refresh(ownerNode, nodeContainer, nodeFactory, newReference.Index);
                        }
                    }
                }
                references = newReferences;
                indices    = newReferences.Select(x => x.Index).ToList();
            }
        }
Beispiel #15
0
        /// <inheritdoc/>
        public IGraphNode Build(object obj, Guid guid, NodeFactoryDelegate nodeFactory)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }
            if (nodeFactory == null)
            {
                throw new ArgumentNullException(nameof(nodeFactory));
            }
            Reset();
            rootGuid = guid;
            var typeDescriptor = TypeDescriptorFactory.Find(obj.GetType());

            currentNodeFactory = nodeFactory;
            VisitObject(obj, typeDescriptor as ObjectDescriptor, true);
            currentNodeFactory = null;
            return(rootNode);
        }
Beispiel #16
0
        /// <summary>
        /// Gets the node associated to a data object, if it exists, otherwise creates a new node for the object and its member recursively.
        /// </summary>
        /// <param name="rootObject">The data object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>The <see cref="IGraphNode"/> associated to the given object.</returns>
        internal IGraphNode GetOrCreateNode(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (nodeFactory == null)
            {
                throw new ArgumentNullException(nameof(nodeFactory));
            }

            if (rootObject == null)
            {
                return(null);
            }

            lock (lockObject)
            {
                IGraphNode result = null;
                if (guidContainer != null && !rootObject.GetType().IsValueType)
                {
                    result = GetNode(rootObject);
                }

                return(result ?? CreateNode(rootObject, nodeFactory));
            }
        }
Beispiel #17
0
        /// <summary>
        /// Gets the node associated to a data object, if it exists, otherwise creates a new node for the object and its member recursively.
        /// </summary>
        /// <param name="rootObject">The data object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>The <see cref="IGraphNode"/> associated to the given object.</returns>
        internal IGraphNode GetOrCreateNodeInternal(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (nodeFactory == null)
            {
                throw new ArgumentNullException(nameof(nodeFactory));
            }

            if (rootObject == null)
            {
                return(null);
            }

            lock (lockObject)
            {
                IGraphNode result;
                if (!rootObject.GetType().IsValueType)
                {
                    result = GetNodeInternal(rootObject);
                    if (result != null)
                    {
                        return(result);
                    }
                }

                var guid = !rootObject.GetType().IsValueType ? guidContainer.GetOrCreateGuid(rootObject) : Guid.NewGuid();
                result = NodeBuilder.Build(rootObject, guid, nodeFactory);

                if (result != null)
                {
                    // Register reference objects
                    nodesByGuid.Add(result.Guid, result);
                    // Create or update nodes of referenced objects
                    UpdateReferencesInternal(result);
                }
                return(result);
            }
        }
 public FunctionalNodeProvider(string path, NodeFactoryDelegate factoryMethod)
 {
     Path = path;
     ParentPath = N2.Web.Url.RemoveLastSegment(Path);
     FactoryMethod = factoryMethod;
 }
Beispiel #19
0
        private void UpdateOrCreateReferenceTarget(IReference reference, IGraphNode node, NodeFactoryDelegate nodeFactory, Stack <object> indices = null)
        {
            if (reference == null)
            {
                throw new ArgumentNullException(nameof(reference));
            }
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            var content = (ContentBase)node.Content;

            var referenceEnumerable = reference as ReferenceEnumerable;

            if (referenceEnumerable != null)
            {
                if (indices == null)
                {
                    indices = new Stack <object>();
                }

                foreach (var itemReference in referenceEnumerable)
                {
                    indices.Push(itemReference.Index);
                    UpdateOrCreateReferenceTarget(itemReference, node, nodeFactory, indices);
                    indices.Pop();
                }
            }
            else
            {
                if (content.ShouldProcessReference)
                {
                    var singleReference = ((ObjectReference)reference);
                    if (singleReference.TargetNode != null && singleReference.TargetNode.Content.Value != reference.ObjectValue)
                    {
                        singleReference.Clear();
                    }

                    if (singleReference.TargetNode == null && reference.ObjectValue != null)
                    {
                        // This call will recursively update the references.
                        var target = singleReference.SetTarget(this, nodeFactory);
                        if (target != null)
                        {
                            var structContent = target.Content as BoxedContent;
                            if (structContent != null)
                            {
                                structContent.BoxedStructureOwner        = content;
                                structContent.BoxedStructureOwnerIndices = indices?.Reverse().ToArray();
                            }
                        }
                        else
                        {
                            content.ShouldProcessReference = false;
                        }
                    }
                }
            }
        }
        public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            var newObjectValue = ownerNode.Content.Value;

            if (!(newObjectValue is IEnumerable))
            {
                throw new ArgumentException(@"The object is not an IEnumerable", nameof(newObjectValue));
            }

            ObjectValue = newObjectValue;

            var newReferences = new HybridDictionary <Index, ObjectReference>();

            if (IsDictionary)
            {
                foreach (var item in (IEnumerable)ObjectValue)
                {
                    var key   = GetKey(item);
                    var value = (ObjectReference)Reference.CreateReference(GetValue(item), elementType, key);
                    newReferences.Add(key, value);
                }
            }
            else
            {
                var i = 0;
                foreach (var item in (IEnumerable)ObjectValue)
                {
                    var key   = new Index(i);
                    var value = (ObjectReference)Reference.CreateReference(item, elementType, key);
                    newReferences.Add(key, value);
                    ++i;
                }
            }

            // The reference need to be updated if it has never been initialized, if the number of items is different, or if any index or any value is different.
            var needUpdate = items == null || newReferences.Count != items.Count || !AreItemsEqual(items, newReferences);

            if (needUpdate)
            {
                // We create a mapping values of the old list of references to their corresponding target node. We use a list because we can have multiple times the same target in items.
                var oldReferenceMapping = new List <KeyValuePair <object, ObjectReference> >();
                if (items != null)
                {
                    oldReferenceMapping.AddRange(items.Values.Where(x => x.ObjectValue != null && !(x.TargetNode?.Content is BoxedContent)).Select(x => new KeyValuePair <object, ObjectReference>(x.ObjectValue, x)));
                }

                foreach (var newReference in newReferences)
                {
                    if (newReference.Value.ObjectValue != null)
                    {
                        var found = false;
                        var i     = 0;
                        foreach (var item in oldReferenceMapping)
                        {
                            if (Equals(newReference.Value.ObjectValue, item.Key))
                            {
                                // If this value was already present in the old list of reference, just use the same target node in the new list.
                                newReference.Value.SetTarget(item.Value.TargetNode);
                                // Remove consumed existing reference so if there is a second entry with the same "key", it will be the other reference that will be used.
                                oldReferenceMapping.RemoveAt(i);
                                found = true;
                                break;
                            }
                            ++i;
                        }
                        if (!found)
                        {
                            // Otherwise, do a full update that will properly initialize the new reference.
                            newReference.Value.Refresh(ownerNode, nodeContainer, nodeFactory, newReference.Key);
                        }
                    }
                }
                items = newReferences;
                // Remark: this works because both KeyCollection and List implements IReadOnlyCollection. Any internal change to HybridDictionary might break this!
                Indices = (IReadOnlyCollection <Index>)newReferences.Keys;
            }
        }
Beispiel #21
0
        /// <summary>
        /// Creates a graph node.
        /// </summary>
        /// <param name="rootObject">The root object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>A new graph node representing the given root object.</returns>
        private IGraphNode CreateNode(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (rootObject == null) throw new ArgumentNullException(nameof(rootObject));

            Guid guid = Guid.NewGuid();

            // Retrieve results
            if (guidContainer != null && !rootObject.GetType().IsValueType)
                guid = guidContainer.GetOrCreateGuid(rootObject);

            var result = (GraphNode)NodeBuilder.Build(rootObject, guid, nodeFactory);

            if (result != null)
            {
                // Register the factory used to create this node.
                factoriesByNode.Add(result, nodeFactory);
                // Register reference objects
                nodesByGuid.Add(result.Guid, result);
                // Create or update nodes of referenced objects
                UpdateReferences(result);
            }

            return result;
        }
Beispiel #22
0
        private void UpdateOrCreateReferenceTarget(IReference reference, IGraphNode node, NodeFactoryDelegate nodeFactory, Stack<object> indices = null)
        {
            if (reference == null) throw new ArgumentNullException(nameof(reference));
            if (node == null) throw new ArgumentNullException(nameof(node));

            var content = (ContentBase)node.Content;

            var referenceEnumerable = reference as ReferenceEnumerable;
            if (referenceEnumerable != null)
            {
                if (indices == null)
                    indices = new Stack<object>();

                foreach (var itemReference in referenceEnumerable)
                {
                    indices.Push(itemReference.Index);
                    UpdateOrCreateReferenceTarget(itemReference, node, nodeFactory, indices);
                    indices.Pop();
                }
            }
            else
            {
                if (content.ShouldProcessReference)
                {
                    var singleReference = ((ObjectReference)reference);
                    if (singleReference.TargetNode != null && singleReference.TargetNode.Content.Value != reference.ObjectValue)
                    {
                        singleReference.Clear();
                    }

                    if (singleReference.TargetNode == null && reference.ObjectValue != null)
                    {
                        // This call will recursively update the references.
                        var target = singleReference.SetTarget(this, nodeFactory);
                        if (target != null)
                        {                 
                            var structContent = target.Content as BoxedContent;
                            if (structContent != null)
                            {
                                structContent.BoxedStructureOwner = content;
                                structContent.BoxedStructureOwnerIndices = indices?.Reverse().ToArray();
                            }
                        }
                        else
                        {
                            content.ShouldProcessReference = false;
                        }
                    }
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Set the <see cref="TargetNode"/> and <see cref="TargetGuid"/> of the targeted object by retrieving it from or creating it to the given <see cref="NodeContainer"/>.
        /// </summary>
        /// <param name="objectValue">The value for which to set the target node.</param>
        /// <param name="nodeContainer">The <see cref="NodeContainer"/> used to retrieve or create the target node.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        internal IGraphNode SetTarget(object objectValue, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
        {
            if (nodeContainer == null)
            {
                throw new ArgumentNullException(nameof(nodeContainer));
            }
            IGraphNode targetNode = nodeContainer.GetOrCreateNodeInternal(objectValue, nodeFactory);

            SetTarget(targetNode);
            return(targetNode);
        }
Beispiel #24
0
        /// <summary>
        /// Gets the node associated to a data object, if it exists, otherwise creates a new node for the object and its member recursively.
        /// </summary>
        /// <param name="rootObject">The data object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>The <see cref="IGraphNode"/> associated to the given object.</returns>
        internal IGraphNode GetOrCreateNode(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (nodeFactory == null) throw new ArgumentNullException(nameof(nodeFactory));

            if (rootObject == null)
                return null;

            lock (lockObject)
            {
                IGraphNode result = null;
                if (guidContainer != null && !rootObject.GetType().IsValueType)
                {
                    result = GetNode(rootObject);
                }

                return result ?? CreateNode(rootObject, nodeFactory);
            }
        }
Beispiel #25
0
 public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
 {
     Refresh(ownerNode, nodeContainer, nodeFactory, Index.Empty);
 }
 public void Refresh(IGraphNode ownerNode, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
 {
     Refresh(ownerNode, nodeContainer, nodeFactory, Index.Empty);
 }
 /// <summary>
 /// Set the <see cref="TargetNode"/> and <see cref="TargetGuid"/> of the targeted object by retrieving it from or creating it to the given <see cref="NodeContainer"/>.
 /// </summary>
 /// <param name="objectValue">The value for which to set the target node.</param>
 /// <param name="nodeContainer">The <see cref="NodeContainer"/> used to retrieve or create the target node.</param>
 /// <param name="nodeFactory">The factory to use to create nodes.</param>
 internal IGraphNode SetTarget(object objectValue, NodeContainer nodeContainer, NodeFactoryDelegate nodeFactory)
 {
     if (nodeContainer == null) throw new ArgumentNullException(nameof(nodeContainer));
     IGraphNode targetNode = nodeContainer.GetOrCreateNodeInternal(objectValue, nodeFactory);
     SetTarget(targetNode);
     return targetNode;
 }
Beispiel #28
0
 public FunctionalNodeProvider(string path, NodeFactoryDelegate factoryMethod)
 {
     Path          = path;
     ParentPath    = N2.Web.Url.RemoveLastSegment(Path);
     FactoryMethod = factoryMethod;
 }
Beispiel #29
0
        /// <summary>
        /// Gets the node associated to a data object, if it exists, otherwise creates a new node for the object and its member recursively.
        /// </summary>
        /// <param name="rootObject">The data object.</param>
        /// <param name="nodeFactory">The factory to use to create nodes.</param>
        /// <returns>The <see cref="IGraphNode"/> associated to the given object.</returns>
        internal IGraphNode GetOrCreateNodeInternal(object rootObject, NodeFactoryDelegate nodeFactory)
        {
            if (nodeFactory == null) throw new ArgumentNullException(nameof(nodeFactory));

            if (rootObject == null)
                return null;

            lock (lockObject)
            {
                IGraphNode result;
                if (!rootObject.GetType().IsValueType)
                {
                    result = GetNodeInternal(rootObject);
                    if (result != null)
                        return result;
                }

                var guid = !rootObject.GetType().IsValueType ? guidContainer.GetOrCreateGuid(rootObject) : Guid.NewGuid();
                result = NodeBuilder.Build(rootObject, guid, nodeFactory);

                if (result != null)
                {
                    // Register reference objects
                    nodesByGuid.Add(result.Guid, result);
                    // Create or update nodes of referenced objects
                    UpdateReferencesInternal(result);
                }
                return result;
            }
        }