// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// STUBS ONLY
-
#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;
+ }
+ _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 ()
{
- throw new NotImplementedException ();
+ return new CodeDomSerializationStore (_provider);
+ }
+
+ public override SerializationStore LoadStore (Stream stream)
+ {
+ return CodeDomSerializationStore.Load (stream);
}
public override ICollection Deserialize (SerializationStore store)
{
- throw new NotImplementedException ();
+ return this.Deserialize (store, null);
}
public override ICollection Deserialize (SerializationStore store, IContainer container)
{
- throw new NotImplementedException ();
+ return DeserializeCore (store, container, true, true);
}
- public override SerializationStore LoadStore (Stream stream)
+ public override void DeserializeTo (SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
{
- throw new NotImplementedException ();
+ 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)
{
- throw new NotImplementedException ();
+ SerializeCore (store, value, false);
}
public override void SerializeAbsolute (SerializationStore store, object value)
{
- throw new NotImplementedException ();
+ SerializeCore (store, value, true);
}
public override void SerializeMember (SerializationStore store, object owningObject, MemberDescriptor member)
{
- throw new NotImplementedException ();
+ SerializeMemberCore (store, owningObject, member, false);
}
public override void SerializeMemberAbsolute (SerializationStore store, object owningObject, MemberDescriptor member)
{
- throw new NotImplementedException ();
+ SerializeMemberCore (store, owningObject, member, true);
}
- public override void DeserializeTo (SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
+ 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)
{
- throw new NotImplementedException ();
+ 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);
}
}
}