4 using System.Collections.Generic;
7 using SiliconStudio.Core.Extensions;
8 using SiliconStudio.Quantum.Contents;
9 using SiliconStudio.Quantum.References;
11 namespace SiliconStudio.Quantum
18 private readonly Dictionary<Guid, IModelNode> modelsByGuid =
new Dictionary<Guid, IModelNode>();
27 if (instantiateGuidContainer)
29 NodeBuilder = CreateDefaultNodeBuilder();
39 if (guidContainer == null)
throw new ArgumentNullException(
"guidContainer");
40 this.guidContainer = guidContainer;
41 NodeBuilder = CreateDefaultNodeBuilder();
66 if (guidContainer == null)
throw new InvalidOperationException(
"This ModelContainer has no GuidContainer and can't retrieve Guid associated to a data object.");
67 Guid guid = guidContainer.GetGuid(rootObject);
68 return guid == Guid.Empty ? null : GetModelNode(guid);
79 return modelsByGuid.TryGetValue(guid, out result) ? result : null;
88 public Guid
GetGuid(
object rootObject, Type type)
90 if (guidContainer == null)
throw new InvalidOperationException(
"This ModelContainer has no GuidContainer and can't retrieve Guid associated to a data object.");
91 return guidContainer.GetGuid(rootObject);
103 if (guidContainer != null && (rootObject == null || !rootObject.GetType().IsValueType))
105 result = GetModelNode(rootObject);
108 return result ?? CreateModelNode(rootObject, type);
118 if (guidContainer != null)
120 guidContainer.UnregisterGuid(guid);
122 return modelsByGuid.Remove(guid);
130 if (guidContainer != null)
132 guidContainer.Clear();
134 modelsByGuid.Clear();
143 UpdateReferences(node,
true);
148 var guidToRemove = modelsByGuid.Keys.ToDictionary(guid => guid);
149 foreach (var obj
in objectsToKeep)
151 CollectGarbageRecursively(obj, guidToRemove);
154 foreach (var guid
in guidToRemove.Where(x => x.Value != Guid.Empty).Select(x => x.Value))
156 guidContainer.UnregisterGuid(guid);
157 modelsByGuid.Remove(guid);
163 private void CollectGarbageRecursively(
object obj, Dictionary<Guid, Guid> guidToRemove)
165 var model = GetModelNode(obj);
168 guidToRemove[model.Guid] = Guid.Empty;
169 foreach (var child
in model.Children)
171 if (child.Content.IsReference)
177 foreach (var itemRef
in enumRef)
179 CollectGarbageRecursively(itemRef.ObjectValue, guidToRemove);
184 CollectGarbageRecursively(objRef.ObjectValue, guidToRemove);
191 private IModelNode CreateModelNode(
object rootObject, Type type)
193 if (rootObject != null && !type.IsInstanceOfType(rootObject))
throw new ArgumentException(
@"The given type does not match the given object.",
"rootObject");
195 Guid guid = Guid.NewGuid();
198 if (guidContainer != null && rootObject != null && !rootObject.GetType().IsValueType)
199 guid = guidContainer.GetOrCreateGuid(rootObject);
201 IModelNode result = NodeBuilder.Build(rootObject, type, guid);
206 modelsByGuid.Add(result.Guid, result);
209 UpdateReferences(result,
false);
215 private void UpdateReferences(IModelNode node,
bool refreshReferences)
218 if (node.Content.IsReference)
220 if (refreshReferences)
221 node.Content.Reference.Refresh(node.Content.Value);
223 UpdateOrCreateReferenceTarget(node.Content.Reference, node.Content, refreshReferences);
228 foreach (var child
in node.Children.SelectDeep(x => x.Children).Where(x => x.Content.IsReference))
230 if (refreshReferences)
231 child.Content.Reference.Refresh(child.Content.Value);
233 UpdateOrCreateReferenceTarget(child.Content.Reference, child.Content, refreshReferences);
238 private void UpdateOrCreateReferenceTarget(
IReference reference,
IContent content,
bool refreshReferences, Stack<object> indices = null)
240 if (reference == null)
throw new ArgumentNullException(
"reference");
241 if (content == null)
throw new ArgumentNullException(
"content");
244 if (referenceEnumerable != null)
247 indices =
new Stack<object>();
249 foreach (var itemReference
in referenceEnumerable)
251 indices.Push(itemReference.Index);
252 UpdateOrCreateReferenceTarget(itemReference, content, refreshReferences, indices);
259 if (singleReference.TargetNode != null && singleReference.TargetNode.Content.Value != reference.
ObjectValue)
261 singleReference.Clear();
264 if (singleReference.TargetNode == null)
266 IModelNode node = GetOrCreateModelNode(reference.
ObjectValue, reference.
Type);
269 singleReference.SetTarget(node);
271 if (structContent != null)
273 structContent.BoxedStructureOwner = content;
274 structContent.BoxedStructureOwnerIndices = indices != null ? indices.Reverse().ToArray() : null;
278 if (singleReference.TargetNode.Content.IsReference)
280 var targetContent = singleReference.TargetNode.Content;
282 if (refreshReferences)
283 targetContent.Reference.Refresh(targetContent.Value);
285 UpdateOrCreateReferenceTarget(targetContent.Reference, targetContent, refreshReferences);
289 foreach (var child
in node.Children.SelectDeep(x => x.Children).Where(x => x.Content.IsReference))
291 if (refreshReferences)
292 child.Content.Reference.Refresh(child.Content.Value);
294 UpdateOrCreateReferenceTarget(child.Content.Reference, child.Content, refreshReferences);
301 private static INodeBuilder CreateDefaultNodeBuilder()
303 var nodeBuilder =
new DefaultModelBuilder();
IModelNode GetModelNode(Guid guid)
Gets the model associated to the given Guid, if it exists.
A container used to store models and resolve references between them.
void UpdateReferences(IModelNode node)
Refresh all references contained in the given node, creating new models for newly referenced objects...
ModelContainer(IGuidContainer guidContainer)
Create a new instance of ModelContainer. This constructor allows to provide a IGuidContainer, in order to share object Guid between different ModelContainer.
bool RemoveModelNode(Guid guid)
Removes a model that was previously registered.
A class representing an enumeration of references to multiple objects.
Base interface for Guid containers, object that can store a unique identifier for a collection of obj...
object ObjectValue
Gets the data object targeted by this reference, if available.
IModelNode GetModelNode(object rootObject)
Gets the model associated to a data object, if it exists. If the ModelContainer has been constructed ...
ModelContainer(bool instantiateGuidContainer=true)
Create a new instance of ModelContainer.
Type Type
Gets the type of object targeted by this reference, if available.
This interface provides objects and methods to build a nodal view model from a given object...
Handles Guid generation and storage for model nodes.
void Clear()
Removes all models that were previously registered.
A class representing a reference to another object that has a different model.
The IModelNode interface represents a node in a model object. A model object is represented by a grap...
Guid GetGuid(object rootObject, Type type)
Gets the Guid associated to a data object, if it exists. If the ModelContainer has been constructed w...
int CollectGarbage(IEnumerable< object > objectsToKeep)
IModelNode GetOrCreateModelNode(object rootObject, Type type)
Gets the model associated to a data object, if it exists, or create a new model for the object otherw...