4 using System.Collections;
5 using System.Collections.Generic;
8 using SiliconStudio.Core.Extensions;
9 using SiliconStudio.Core.Reflection;
11 using SiliconStudio.Quantum.Contents;
12 using SiliconStudio.Quantum.References;
14 namespace SiliconStudio.Quantum
21 private readonly Stack<ModelNode> contextStack =
new Stack<ModelNode>();
22 private readonly HashSet<IContent> referenceContents =
new HashSet<IContent>();
23 private ModelNode rootNode;
24 private Guid rootGuid;
29 public DefaultModelBuilder()
32 AvailableCommands =
new List<INodeCommand>();
45 public event EventHandler<NodeConstructingArgs> NodeConstructing;
48 public event EventHandler<NodeConstructedArgs> NodeConstructed;
53 public override void Reset()
56 rootGuid = Guid.Empty;
58 referenceContents.Clear();
63 public IModelNode Build(
object obj, Type type, Guid guid)
67 var typeDescriptor = TypeDescriptorFactory.Find(obj != null ? obj.GetType() : type);
74 public override void VisitObject(
object obj,
ObjectDescriptor descriptor,
bool visitMembers)
76 bool isRootNode = contextStack.Count == 0;
79 if (!NotifyNodeConstructing(descriptor))
84 IReference reference = CreateReferenceForNode(descriptor.
Type, obj);
87 rootNode =
new ModelNode(descriptor.
Type.Name, content, rootGuid);
88 if (reference != null && descriptor.
Type.IsStruct())
89 throw new QuantumConsistencyException(
"A collection type",
"A structure type", rootNode);
91 if (reference != null)
92 referenceContents.Add(content);
94 AvailableCommands.Where(x => x.CanAttach(rootNode.Content.Descriptor, null)).ForEach(rootNode.AddCommand);
95 NotifyNodeConstructed(content);
102 PushContextNode(rootNode);
105 if (!IsPrimitiveType(descriptor.
Type))
107 base.VisitObject(obj, descriptor,
true);
123 base.VisitCollection(collection, descriptor);
130 if (!IsPrimitiveType(descriptor.
KeyType))
131 throw new InvalidOperationException(
"The type of dictionary key must be a primary type.");
134 if (IsPrimitiveType(descriptor.
ValueType,
false) || IsEnumerable(descriptor.
ValueType))
136 base.VisitDictionary(dictionary, descriptor);
148 var handler = NodeConstructing;
151 var args =
new NodeConstructingArgs(descriptor, null);
153 return !args.Discard;
167 var handler = NodeConstructing;
172 return !args.Discard;
182 internal void NotifyNodeConstructed(
IContent content)
184 var handler = NodeConstructed;
187 var args =
new NodeConstructedArgs(content);
195 if (!NotifyNodeConstructing(containerDescriptor, member))
199 IReference reference = CreateReferenceForNode(member.
Type, value);
200 ModelNode containerNode = GetContextNode();
201 ITypeDescriptor typeDescriptor = TypeDescriptorFactory.Find(member.Type);
202 IContent content =
new MemberContent(containerNode.Content, member, typeDescriptor, IsPrimitiveType(member.
Type), reference);
203 var node =
new ModelNode(member.
Name, content, Guid.NewGuid());
204 containerNode.AddChild(node);
206 if (reference != null)
207 referenceContents.Add(content);
212 PushContextNode(node);
217 AvailableCommands.Where(x => x.CanAttach(node.Content.Descriptor, (
MemberDescriptorBase)member)).ForEach(node.AddCommand);
218 NotifyNodeConstructed(content);
223 private IReference CreateReferenceForNode(Type type,
object value)
226 if ((!type.IsClass && !type.IsInterface) || IsPrimitiveType(type))
229 ITypeDescriptor descriptor = value != null ? TypeDescriptorFactory.Find(value.GetType()) : null;
230 var valueType = GetElementValueType(descriptor);
233 if (valueType == null || !IsPrimitiveType(valueType,
false))
234 return Reference.CreateReference(value, type, Reference.NotInCollection);
239 private void PushContextNode(ModelNode node)
241 contextStack.Push(node);
244 private void PopContextNode()
249 private ModelNode GetContextNode()
251 return contextStack.Peek();
254 private static bool IsEnumerable(Type type)
259 private bool IsPrimitiveType(Type type,
bool includeAdditionalPrimitiveTypes =
true)
264 if (type.IsNullable())
265 type =
Nullable.GetUnderlyingType(type);
267 return type.IsPrimitive || type == typeof(
string) || type.IsEnum || (includeAdditionalPrimitiveTypes && PrimitiveTypes.Any(x => x.IsAssignableFrom(type)));
274 if (dictionaryDescriptor != null)
276 return dictionaryDescriptor.ValueType;
278 return collectionDescriptor != null ? collectionDescriptor.ElementType : null;
Provides a descriptor for a System.Collections.ICollection.
Type ElementType
Gets or sets the type of the element.
string Name
Gets the name.
Default implementation of a ITypeDescriptor.
A visitor for serializable data (binary, yaml and editor).
Describe a member of an object.
A class representing an enumeration of references to multiple objects.
An implementation of IContent that gives access to an object or a boxed struct.
Provides a descriptor for a System.Collections.IDictionary.
An implementation of IContent that gives access to a member of an object.
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
Type ValueType
Gets the type of the value.
Provides access members of a type.
Base class for IMemberDescriptor for a MemberInfo
The device failed due to a badly formed command. This is a run-time issue; The application should des...
A class representing a reference to another object that has a different model.
Type KeyType
Gets the type of the key.