/mcs/class/System.Design/System.ComponentModel.Design.Serialization/CodeDomComponentSerializationService.cs
C# | 589 lines | 461 code | 84 blank | 44 comment | 88 complexity | 5181726906b2b899f33582a18814750d MD5 | raw file
- //
- // System.ComponentModel.Design.Serialization.CodeDomComponentSerializationService
- //
- // Authors:
- // Ivan N. Zlatev (contact@i-nZ.net)
- //
- // (C) 2007 Ivan N. Zlatev
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- #if NET_2_0
- using System;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.ComponentModel;
- using System.ComponentModel.Design.Serialization;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- namespace System.ComponentModel.Design.Serialization
- {
- // A ComponentSerializationService that uses a CodeDomSerializationStore
- // to serialize Components and MemberDescriptors to CodeStatement and CodeStatementCollection
- //
- public sealed class CodeDomComponentSerializationService : ComponentSerializationService
- {
- [Serializable]
- private class CodeDomSerializationStore : SerializationStore, ISerializable
- {
- [Serializable]
- private class Entry
- {
- private bool _isSerialized;
- private object _serialized;
- private bool _absolute;
- private string _name;
- protected Entry ()
- {
- }
- public Entry (string name)
- {
- if (name == null)
- throw new ArgumentNullException ("name");
- _name = name;
- _isSerialized = false;
- _absolute = false;
- }
- public bool IsSerialized {
- get { return _isSerialized; }
- set { _isSerialized = value; }
- }
- public object Serialized {
- get { return _serialized; }
- set {
- _serialized = value;
- _isSerialized = true;
- }
- }
- public bool Absolute {
- get { return _absolute; }
- set { _absolute = value; }
- }
- public string Name {
- get { return _name; }
- set { _name = value; }
- }
- }
- [Serializable]
- private class MemberEntry : Entry
- {
- private MemberDescriptor _descriptor;
- protected MemberEntry ()
- {
- }
- public MemberEntry (MemberDescriptor descriptor)
- {
- if (descriptor == null)
- throw new ArgumentNullException ("descriptor");
- _descriptor = descriptor;
- base.Name = descriptor.Name;
- }
- public MemberDescriptor Descriptor {
- get { return _descriptor; }
- set { _descriptor = value; }
- }
- }
- [Serializable]
- private class ObjectEntry : Entry
- {
- private Type _type;
- [NonSerialized]
- private object _instance;
- private Dictionary<string,MemberEntry> _members;
- private bool _entireObject;
- protected ObjectEntry ()
- {
- }
- public ObjectEntry (object instance, string name) : base (name)
- {
- if (instance == null)
- throw new ArgumentNullException ("instance");
- _instance = instance;
- _type = instance.GetType ();
- _entireObject = false;
- }
- public Type Type {
- get { return _type; }
- }
- public object Instance {
- get { return _instance; }
- set {
- _instance = value;
- if (value != null)
- _type = value.GetType ();
- }
- }
- public Dictionary<string,MemberEntry> Members {
- get {
- if (_members == null)
- _members = new Dictionary <string, MemberEntry> ();
- return _members;
- }
- set { _members = value; }
- }
- public bool IsEntireObject {
- get { return _entireObject; }
- set { _entireObject = value; }
- }
- }
- // When e.g Copy->Pasting a component will not be preserved, but the serialized
- // data will contain references to the original component name. We handle this
- // here by checking whether CreateInstance returns a component with a different
- // name and we map the old name to the new one so that GetInstance will return
- // a reference to the new component.
- //
- private class InstanceRedirectorDesignerSerializationManager : IDesignerSerializationManager, IServiceProvider
- {
- DesignerSerializationManager _manager;
- private Dictionary <string, string> _nameMap;
- public InstanceRedirectorDesignerSerializationManager (IServiceProvider provider, IContainer container,
- bool validateRecycledTypes)
- {
- if (provider == null)
- throw new ArgumentNullException ("provider");
- DesignerSerializationManager manager = new DesignerSerializationManager (provider);
- manager.PreserveNames = false;
- if (container != null)
- manager.Container = container;
- manager.ValidateRecycledTypes = validateRecycledTypes;
- _manager = manager;
- }
- public IDisposable CreateSession ()
- {
- return _manager.CreateSession ();
- }
- public IList Errors {
- get { return _manager.Errors; }
- }
- object IServiceProvider.GetService (Type service)
- {
- return ((IServiceProvider)_manager).GetService (service);
- }
- #region IDesignerSerializationManager Wrapper Implementation
- void IDesignerSerializationManager.AddSerializationProvider (IDesignerSerializationProvider provider)
- {
- ((IDesignerSerializationManager)_manager).AddSerializationProvider (provider);
- }
- void IDesignerSerializationManager.RemoveSerializationProvider (IDesignerSerializationProvider provider)
- {
- ((IDesignerSerializationManager)_manager).RemoveSerializationProvider (provider);
- }
- object IDesignerSerializationManager.CreateInstance (Type type, ICollection arguments, string name, bool addToContainer)
- {
- object instance = ((IDesignerSerializationManager)_manager).CreateInstance (type, arguments, name, addToContainer);
- string newName = ((IDesignerSerializationManager)_manager).GetName (instance);
- if (newName != name) {
- if (_nameMap == null)
- _nameMap = new Dictionary<string, string> ();
- _nameMap[name] = newName;
- }
- return instance;
- }
- object IDesignerSerializationManager.GetInstance (string name)
- {
- if (_nameMap != null && _nameMap.ContainsKey (name))
- return ((IDesignerSerializationManager)_manager).GetInstance (_nameMap[name]);
- return ((IDesignerSerializationManager)_manager).GetInstance (name);
- }
- Type IDesignerSerializationManager.GetType (string name)
- {
- return ((IDesignerSerializationManager)_manager).GetType (name);
- }
- object IDesignerSerializationManager.GetSerializer (Type type, Type serializerType)
- {
- return ((IDesignerSerializationManager)_manager).GetSerializer (type, serializerType);
- }
- string IDesignerSerializationManager.GetName (object instance)
- {
- return ((IDesignerSerializationManager)_manager).GetName (instance);
- }
- void IDesignerSerializationManager.SetName (object instance, string name)
- {
- ((IDesignerSerializationManager)_manager).SetName (instance, name);
- }
- void IDesignerSerializationManager.ReportError (object error)
- {
- ((IDesignerSerializationManager)_manager).ReportError (error);
- }
- ContextStack IDesignerSerializationManager.Context {
- get { return ((IDesignerSerializationManager)_manager).Context; }
- }
- PropertyDescriptorCollection IDesignerSerializationManager.Properties {
- get { return ((IDesignerSerializationManager)_manager).Properties; }
- }
- event EventHandler IDesignerSerializationManager.SerializationComplete {
- add { ((IDesignerSerializationManager)_manager).SerializationComplete += value; }
- remove { ((IDesignerSerializationManager)_manager).SerializationComplete -= value; }
- }
- event ResolveNameEventHandler IDesignerSerializationManager.ResolveName {
- add { ((IDesignerSerializationManager)_manager).ResolveName += value; }
- remove { ((IDesignerSerializationManager)_manager).ResolveName -= value; }
- }
- #endregion
- } // InstanceRedirectorDesignerSerializationManager
- private bool _closed;
- private Dictionary <string, ObjectEntry> _objects;
- private IServiceProvider _provider;
- private ICollection _errors;
- internal CodeDomSerializationStore () : this (null)
- {
- }
- internal CodeDomSerializationStore (IServiceProvider provider)
- {
- _provider = provider;
- }
- private CodeDomSerializationStore (SerializationInfo info, StreamingContext context)
- {
- _objects = (Dictionary<string, ObjectEntry>) info.GetValue ("objects", typeof (Dictionary<string, ObjectEntry>));
- _closed = (bool) info.GetValue ("closed", typeof (bool));
- }
- void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
- {
- info.AddValue ("objects", _objects);
- info.AddValue ("closed", _closed);
- }
- public override void Close ()
- {
- if (!_closed) {
- Serialize (_provider);
- _closed = true;
- }
- }
- internal static CodeDomSerializationStore Load (Stream stream)
- {
- return new BinaryFormatter ().Deserialize (stream) as CodeDomSerializationStore;
- }
- public override void Save (Stream stream)
- {
- Close ();
- new BinaryFormatter ().Serialize (stream, this);
- }
- private void Serialize (IServiceProvider provider)
- {
- if (provider == null || _objects == null)
- return;
- // Use a new serialization manager to prevent from "deadlocking" the surface one
- // by trying to create new session when one currently exists
- //
- InstanceRedirectorDesignerSerializationManager manager =
- new InstanceRedirectorDesignerSerializationManager (provider, null, false);
- ((IDesignerSerializationManager)manager).AddSerializationProvider (CodeDomSerializationProvider.Instance);
- IDisposable session = manager.CreateSession ();
- foreach (ObjectEntry objectEntry in _objects.Values) {
- if (objectEntry.IsEntireObject) {
- CodeDomSerializer serializer = (CodeDomSerializer) ((IDesignerSerializationManager)manager).GetSerializer (objectEntry.Type,
- typeof (CodeDomSerializer));
- if (serializer != null) {
- object serialized = null;
- if (objectEntry.Absolute)
- serialized = serializer.SerializeAbsolute (manager,
- objectEntry.Instance);
- else
- serialized = serializer.Serialize (manager, objectEntry.Instance);
- objectEntry.Serialized = serialized;
- }
- } else {
- foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
- CodeDomSerializer serializer = (CodeDomSerializer) ((IDesignerSerializationManager)manager).GetSerializer (
- objectEntry.Type, typeof (CodeDomSerializer));
- if (serializer != null) {
- object serialized = null;
- if (memberEntry.Absolute) {
- serialized = serializer.SerializeMemberAbsolute (manager,
- objectEntry.Instance,
- memberEntry.Descriptor);
- } else {
- serialized = serializer.SerializeMember (manager,
- objectEntry.Instance,
- memberEntry.Descriptor);
- }
- memberEntry.Serialized = serialized;
- }
- }
- }
- }
- _errors = manager.Errors;
- session.Dispose ();
- }
- internal void AddObject (object instance, bool absolute)
- {
- if (_closed)
- throw new InvalidOperationException ("store is closed");
- if (_objects == null)
- _objects = new Dictionary <string, ObjectEntry> ();
- string objectName = GetName (instance);
- if (!_objects.ContainsKey (objectName)) {
- ObjectEntry objectEntry = new ObjectEntry (instance, objectName);
- objectEntry.Absolute = absolute;
- objectEntry.IsEntireObject = true;
- _objects[objectName] = objectEntry;
- }
- }
- internal void AddMember (object owner, MemberDescriptor member, bool absolute)
- {
- if (_closed)
- throw new InvalidOperationException ("store is closed");
- if (member == null)
- throw new ArgumentNullException ("member");
- if (owner == null)
- throw new ArgumentNullException ("owner");
- if (_objects == null)
- _objects = new Dictionary <string, ObjectEntry> ();
- string objectName = GetName (owner);
- if (!_objects.ContainsKey (objectName))
- _objects.Add (objectName, new ObjectEntry (owner, objectName));
- MemberEntry memberEntry = new MemberEntry (member);
- memberEntry.Absolute = absolute;
- _objects[objectName].Members[member.Name] = memberEntry;
- }
- private string GetName (object value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- string name = null;
- IComponent component = value as IComponent;
- if (component != null && component.Site != null) {
- if (component.Site is INestedSite)
- name = ((INestedSite)component.Site).FullName;
- else
- name = component.Site != null ? component.Site.Name : null;
- } else if (value is MemberDescriptor) {
- name = ((MemberDescriptor) value).Name;
- } else {
- name = value.GetHashCode ().ToString ();
- }
- return name;
- }
- internal ICollection Deserialize (IServiceProvider provider, IContainer container,
- bool validateRecycledTypes, bool applyDefaults)
- {
- List<object> objectInstances = new List<object> ();
- if (provider == null || _objects == null)
- return objectInstances;
- _provider = provider;
- // Use a new serialization manager to prevent from "deadlocking" the surface one
- // by trying to create new session when one currently exists
- //
- InstanceRedirectorDesignerSerializationManager manager =
- new InstanceRedirectorDesignerSerializationManager (provider, container, validateRecycledTypes);
- ((IDesignerSerializationManager)manager).AddSerializationProvider (CodeDomSerializationProvider.Instance);
- IDisposable session = manager.CreateSession ();
- foreach (ObjectEntry entry in _objects.Values)
- objectInstances.Add (DeserializeEntry (manager, entry));
- _errors = manager.Errors;
- session.Dispose ();
- return objectInstances;
- }
- private object DeserializeEntry (IDesignerSerializationManager manager, ObjectEntry objectEntry)
- {
- object deserialized = null;
- if (objectEntry.IsEntireObject) {
- CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
- typeof (CodeDomSerializer));
- if (serializer != null) {
- deserialized = serializer.Deserialize (manager, objectEntry.Serialized);
- // check if the name of the object has changed
- // (if it e.g clashes with another name)
- string newName = manager.GetName (deserialized);
- if (newName != objectEntry.Name)
- objectEntry.Name = newName;
- }
- } else {
- foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
- CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
- typeof (CodeDomSerializer));
- if (serializer != null)
- serializer.Deserialize (manager, memberEntry.Serialized);
- }
- }
- return deserialized;
- }
- public override ICollection Errors {
- get {
- if (_errors == null)
- _errors = new object[0];
- return _errors;
- }
- }
- } // CodeDomSerializationStore
- private IServiceProvider _provider;
- public CodeDomComponentSerializationService () : this (null)
- {
- }
- public CodeDomComponentSerializationService (IServiceProvider provider)
- {
- _provider = provider;
- }
- public override SerializationStore CreateStore ()
- {
- return new CodeDomSerializationStore (_provider);
- }
- public override SerializationStore LoadStore (Stream stream)
- {
- return CodeDomSerializationStore.Load (stream);
- }
- public override ICollection Deserialize (SerializationStore store)
- {
- return this.Deserialize (store, null);
- }
- public override ICollection Deserialize (SerializationStore store, IContainer container)
- {
- return DeserializeCore (store, container, true, true);
- }
- public override void DeserializeTo (SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
- {
- DeserializeCore (store, container, validateRecycledTypes, applyDefaults);
- }
- private ICollection DeserializeCore (SerializationStore store, IContainer container, bool validateRecycledTypes,
- bool applyDefaults)
- {
- CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
- if (codeDomStore == null)
- throw new InvalidOperationException ("store type unsupported");
- return codeDomStore.Deserialize (_provider, container, validateRecycledTypes, applyDefaults);
- }
- public override void Serialize (SerializationStore store, object value)
- {
- SerializeCore (store, value, false);
- }
- public override void SerializeAbsolute (SerializationStore store, object value)
- {
- SerializeCore (store, value, true);
- }
- public override void SerializeMember (SerializationStore store, object owningObject, MemberDescriptor member)
- {
- SerializeMemberCore (store, owningObject, member, false);
- }
- public override void SerializeMemberAbsolute (SerializationStore store, object owningObject, MemberDescriptor member)
- {
- SerializeMemberCore (store, owningObject, member, true);
- }
- private void SerializeCore (SerializationStore store, object value, bool absolute)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
- if (store == null)
- throw new ArgumentNullException ("store");
- CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
- if (store == null)
- throw new InvalidOperationException ("store type unsupported");
- codeDomStore.AddObject (value, absolute);
- }
- private void SerializeMemberCore (SerializationStore store, object owningObject, MemberDescriptor member, bool absolute)
- {
- if (member == null)
- throw new ArgumentNullException ("member");
- if (owningObject == null)
- throw new ArgumentNullException ("owningObject");
- if (store == null)
- throw new ArgumentNullException ("store");
- CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
- if (codeDomStore == null)
- throw new InvalidOperationException ("store type unsupported");
- codeDomStore.AddMember (owningObject, member, absolute);
- }
- }
- }
- #endif