2 // System.ComponentModel.Design.Serialization.CodeDomComponentSerializationService
5 // Ivan N. Zlatev (contact@i-nZ.net)
7 // (C) 2007 Ivan N. Zlatev
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Runtime.Serialization;
34 using System.Runtime.Serialization.Formatters.Binary;
35 using System.ComponentModel;
36 using System.ComponentModel.Design.Serialization;
37 using System.Collections;
38 using System.Collections.Generic;
41 namespace System.ComponentModel.Design.Serialization
43 // A ComponentSerializationService that uses a CodeDomSerializationStore
44 // to serialize Components and MemberDescriptors to CodeStatement and CodeStatementCollection
46 public sealed class CodeDomComponentSerializationService : ComponentSerializationService
49 private class CodeDomSerializationStore : SerializationStore
55 private bool _isSerialized;
56 private object _serialized;
57 private object _deserialized;
58 private bool _isDeserialized;
59 private bool _absolute;
66 public Entry (string name)
69 throw new ArgumentNullException ("name");
71 _isDeserialized = true;
72 _isSerialized = false;
76 public bool IsSerialized {
77 get { return _isSerialized; }
78 set { _isSerialized = value; }
81 public object Serialized {
82 get { return _serialized; }
89 public bool IsDeserialized {
90 get { return _isDeserialized; }
91 set { _isDeserialized = value; }
94 public object Deserialized {
95 get { return _deserialized; }
97 _deserialized = value;
98 _isDeserialized = true;
102 public bool Absolute {
103 get { return _absolute; }
104 set { _absolute = value; }
108 get { return _name; }
109 set { _name = value; }
114 private class MemberEntry : Entry
116 private MemberDescriptor _descriptor;
118 protected MemberEntry ()
122 public MemberEntry (MemberDescriptor descriptor)
124 if (descriptor == null)
125 throw new ArgumentNullException ("descriptor");
126 _descriptor = descriptor;
127 base.Name = descriptor.Name;
130 public MemberDescriptor Descriptor {
131 get { return _descriptor; }
132 set { _descriptor = value; }
137 private class ObjectEntry : Entry
141 private object _instance;
142 private Dictionary<string,MemberEntry> _members;
143 private bool _entireObject;
145 protected ObjectEntry ()
149 public ObjectEntry (object instance, string name) : base (name)
151 if (instance == null)
152 throw new ArgumentNullException ("instance");
153 _instance = instance;
154 _type = instance.GetType ();
155 _entireObject = false;
159 get { return _type; }
162 public object Instance {
163 get { return _instance; }
167 _type = value.GetType ();
171 public Dictionary<string,MemberEntry> Members {
173 if (_members == null)
174 _members = new Dictionary <string, MemberEntry> ();
177 set { _members = value; }
180 public bool EntireObject {
181 get { return _entireObject; }
182 set { _entireObject = value; }
186 private bool _closed;
187 private Dictionary <string, ObjectEntry> _objects;
188 private IServiceProvider _provider;
189 private ICollection _errors;
191 internal CodeDomSerializationStore () : this (null)
195 internal CodeDomSerializationStore (IServiceProvider provider)
197 _provider = provider;
200 public override void Close ()
203 Serialize (_provider);
208 internal static CodeDomSerializationStore Load (Stream stream)
210 return new BinaryFormatter ().Deserialize (stream) as CodeDomSerializationStore;
213 public override void Save (Stream stream)
216 new BinaryFormatter ().Serialize (stream, this);
219 private void Serialize (IServiceProvider provider)
221 if (provider == null)
223 DesignerSerializationManager manager = provider.GetService (typeof (IDesignerSerializationManager)) as DesignerSerializationManager;
227 using (IDisposable session = manager.CreateSession ()) {
228 foreach (ObjectEntry objectEntry in _objects.Values) {
229 if (objectEntry.EntireObject) {
230 CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
231 typeof (CodeDomSerializer));
232 if (serializer != null) {
233 object serialized = null;
234 if (objectEntry.Absolute)
235 serialized = serializer.SerializeAbsolute (manager, objectEntry.Instance);
237 serialized = serializer.Serialize (manager, objectEntry.Instance);
238 if (serialized != null)
239 objectEntry.Serialized = serialized;
242 foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
243 CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (
244 objectEntry.Type, typeof (CodeDomSerializer));
245 if (serializer != null) {
246 object serialized = null;
247 if (memberEntry.Absolute) {
248 serialized = serializer.SerializeMemberAbsolute (manager,
249 objectEntry.Instance,
250 memberEntry.Descriptor);
252 serialized = serializer.SerializeMember (manager,
253 objectEntry.Instance,
254 memberEntry.Descriptor);
256 if (serialized != null)
257 memberEntry.Serialized = serialized;
262 _errors = manager.Errors;
266 internal void AddObject (object instance, bool absolute)
269 throw new InvalidOperationException ("store is closed");
271 if (_objects == null)
272 _objects = new Dictionary <string, ObjectEntry> ();
273 string objectName = GetName (instance);
275 if (!_objects.ContainsKey (objectName)) {
276 ObjectEntry objectEntry = new ObjectEntry (instance, objectName);
277 objectEntry.Absolute = absolute;
278 objectEntry.EntireObject = true;
279 _objects[objectName] = objectEntry;
283 internal void AddMember (object owner, MemberDescriptor member, bool absolute)
286 throw new InvalidOperationException ("store is closed");
288 throw new ArgumentNullException ("member");
290 throw new ArgumentNullException ("owner");
292 if (_objects == null)
293 _objects = new Dictionary <string, ObjectEntry> ();
294 string objectName = GetName (owner);
296 if (!_objects.ContainsKey (objectName)) {
297 ObjectEntry objectEntry = new ObjectEntry (owner, objectName);
298 MemberEntry memberEntry = new MemberEntry (member);
299 memberEntry.Absolute = absolute;
300 objectEntry.Members[member.Name] = memberEntry;
301 _objects[objectName] = objectEntry;
305 private string GetName (object value)
309 IComponent component = value as IComponent;
310 if (component != null) {
311 if (component.Site is INestedSite)
312 name = ((INestedSite)component.Site).FullName;
314 name = component.Site != null ? component.Site.Name : null;
315 } else if (value is MemberDescriptor) {
316 name = ((MemberDescriptor) value).Name;
318 name = value.GetHashCode ().ToString ();
324 internal ICollection Deserialize (IServiceProvider provider, IContainer container,
325 bool validateRecycledTypes, bool applyDefaults)
327 List<object> objectInstances = new List<object> ();
329 if (provider == null)
330 return objectInstances;
331 _provider = provider;
333 DesignerSerializationManager manager = provider.GetService
334 (typeof (IDesignerSerializationManager)) as DesignerSerializationManager;
336 return objectInstances;
338 bool validateRecycleBackup = manager.ValidateRecycledTypes;
339 IContainer containerBackup = manager.Container;
341 if (container != null)
342 manager.Container = container;
344 using (IDisposable session = manager.CreateSession ()) {
345 ((IDesignerSerializationManager) manager).ResolveName += OnResolveInstance;
346 foreach (ObjectEntry entry in _objects.Values)
347 objectInstances.Add (DeserializeEntry (manager, entry));
348 ((IDesignerSerializationManager) manager).ResolveName -= OnResolveInstance;
349 _errors = manager.Errors;
352 manager.ValidateRecycledTypes = validateRecycleBackup;
353 manager.Container = containerBackup;
354 return objectInstances;
357 private void OnResolveInstance (object sender, ResolveNameEventArgs args)
359 if (args.Value == null && _objects != null && _objects.ContainsKey (args.Name)) {
360 IDesignerSerializationManager manager = _provider.GetService
361 (typeof (IDesignerSerializationManager)) as IDesignerSerializationManager;
362 if (manager != null) {
363 ObjectEntry entry = _objects[args.Name];
364 if (entry.EntireObject)
365 args.Value = DeserializeEntry (manager, entry);
370 private object DeserializeEntry (IDesignerSerializationManager manager, ObjectEntry objectEntry)
372 object deserialized = null;
374 if (objectEntry.EntireObject) {
375 if (objectEntry.IsDeserialized) {
376 deserialized = objectEntry.Deserialized;
378 CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
379 typeof (CodeDomSerializer));
380 if (serializer != null) {
381 deserialized = serializer.Deserialize (manager, objectEntry.Serialized);
382 objectEntry.Deserialized = deserialized;
383 // check if the name of the object has changed
384 // (if it e.g clashes with another name)
385 string newName = manager.GetName (deserialized);
386 if (newName != objectEntry.Name)
387 objectEntry.Name = newName;
391 foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
392 if (!memberEntry.IsDeserialized) {
393 CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
394 typeof (CodeDomSerializer));
395 if (serializer != null) {
396 serializer.Deserialize (manager, memberEntry.Serialized);
397 memberEntry.IsDeserialized = true;
406 public override ICollection Errors {
409 _errors = new object[0];
413 } // CodeDomSerializationStore
415 private IServiceProvider _provider;
417 public CodeDomComponentSerializationService () : this (null)
421 public CodeDomComponentSerializationService (IServiceProvider provider)
423 _provider = provider;
426 public override SerializationStore CreateStore ()
428 return new CodeDomSerializationStore (_provider);
431 public override SerializationStore LoadStore (Stream stream)
433 return CodeDomSerializationStore.Load (stream);
436 public override ICollection Deserialize (SerializationStore store)
438 return this.Deserialize (store, null);
441 public override ICollection Deserialize (SerializationStore store, IContainer container)
443 return DeserializeCore (store, container, true, true);
446 public override void DeserializeTo (SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
448 DeserializeCore (store, container, validateRecycledTypes, applyDefaults);
451 private ICollection DeserializeCore (SerializationStore store, IContainer container, bool validateRecycledTypes,
454 CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
455 if (codeDomStore == null)
456 throw new InvalidOperationException ("store type unsupported");
457 return codeDomStore.Deserialize (_provider, container, validateRecycledTypes, applyDefaults);
460 public override void Serialize (SerializationStore store, object value)
462 SerializeCore (store, value, false);
465 public override void SerializeAbsolute (SerializationStore store, object value)
467 SerializeCore (store, value, true);
470 public override void SerializeMember (SerializationStore store, object owningObject, MemberDescriptor member)
472 SerializeMemberCore (store, owningObject, member, false);
475 public override void SerializeMemberAbsolute (SerializationStore store, object owningObject, MemberDescriptor member)
477 SerializeMemberCore (store, owningObject, member, true);
480 private void SerializeCore (SerializationStore store, object value, bool absolute)
483 throw new ArgumentNullException ("value");
485 throw new ArgumentNullException ("store");
487 CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
489 throw new InvalidOperationException ("store type unsupported");
491 codeDomStore.AddObject (value, absolute);
494 private void SerializeMemberCore (SerializationStore store, object owningObject, MemberDescriptor member, bool absolute)
497 throw new ArgumentNullException ("member");
498 if (owningObject == null)
499 throw new ArgumentNullException ("owningObject");
501 throw new ArgumentNullException ("store");
503 CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
504 if (codeDomStore == null)
505 throw new InvalidOperationException ("store type unsupported");
506 codeDomStore.AddMember (owningObject, member, absolute);