File: AuthoringOM\Serializer\ActivityCodeDomSerializationManager.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
namespace System.Workflow.ComponentModel.Serialization
{
    using System;
    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.ComponentModel.Design.Serialization;
    using System.Collections;
    using System.Resources;
    using System.Workflow.ComponentModel.Design;
    using System.Collections.Generic;
    using Microsoft.CSharp;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
    using System.CodeDom.Compiler;
    using System.IO;
    using System.Reflection;
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis;
 
    #region Class ActivityCodeDomSerializationManager
    /// <summary>
    /// Serialization manager class for code only serialization which inherits from 
    /// WorkflowMarkupSerializationManager and overrides the GetService method to return the
    /// code-only specific reference service.
    /// </summary>
    /// <remarks>
    /// Due to the fact that the base classes used by the code-only serializer from 
    /// System.Design rely on the reference service to generate code variable ids, we
    /// need to supply our own version of the reference service, since the default
    /// generates invalid variable ids for Activity based classes.
    /// </remarks>
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public class ActivityCodeDomSerializationManager : IDesignerSerializationManager
    {
        private ServiceContainer serviceContainer = null;
        private IDesignerSerializationManager serializationManager;
        private ResolveNameEventHandler resolveNameEventHandler;
        private EventHandler serializationCompleteEventHandler;
 
        public ActivityCodeDomSerializationManager(IDesignerSerializationManager manager)
        {
            if (manager == null)
                throw new ArgumentNullException("manager");
 
            this.serializationManager = manager;
            this.serviceContainer = new ServiceContainer();
            this.serializationManager.ResolveName += new ResolveNameEventHandler(OnResolveName);
            this.serializationManager.SerializationComplete += new EventHandler(OnSerializationComplete);
            if (this.serializationManager is DesignerSerializationManager)
                ((DesignerSerializationManager)this.serializationManager).SessionDisposed += new EventHandler(OnSessionDisposed);
        }
        void OnResolveName(object sender, ResolveNameEventArgs e)
        {
            if (this.resolveNameEventHandler != null)
                this.resolveNameEventHandler(this, e);
        }
 
        void OnSerializationComplete(object sender, EventArgs e)
        {
            if (this.serializationCompleteEventHandler != null)
                this.serializationCompleteEventHandler(this, e);
        }
        void OnSessionDisposed(object sender, EventArgs e)
        {
            try
            {
                if (this.serializationCompleteEventHandler != null)
                    this.serializationCompleteEventHandler(this, EventArgs.Empty);
            }
            finally
            {
                this.resolveNameEventHandler = null;
                this.serializationCompleteEventHandler = null;
            }
        }
        public event System.EventHandler SerializationComplete
        {
            add
            {
                this.serializationCompleteEventHandler += value;
            }
            remove
            {
                this.serializationCompleteEventHandler -= value;
            }
        }
 
        public void SetName(object instance, string name)
        {
            // Need to check this since code dom deserialization tries to 
            // set name twice on all object creation statements.
            if (GetInstance(name) != instance)
                this.serializationManager.SetName(instance, name);
        }
 
 
        [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.LastIndexOf(System.String)", Justification = "This is not a security threat since it is called only in XAML design time scenarios")]
        public string GetName(object value)
        {
            string name = null;
            Activity a = value as Activity;
            if (a != null)
            {
                if (a.Parent == null)
                {
                    name = a.GetValue(WorkflowMarkupSerializer.XClassProperty) as string;
                    if (name != null && name.LastIndexOf(".") > 0)
                        name = name.Substring(name.LastIndexOf('.') + 1);
                }
                else
                    name = a.QualifiedName.Replace('.', '_');
            }
 
            if (name == null)
                name = this.serializationManager.GetName(value);
 
            return name;
        }
 
        /// <summary>
        /// Overridded to force siteing of all Activity based instances created, enabling
        /// code-only programmers to write activity.Activities.Add(new activityType());
        /// </summary>
        public object CreateInstance(Type type, ICollection arguments, string name, bool addToContainer)
        {
            return this.serializationManager.CreateInstance(type, arguments, name, false);
        }
 
        public object GetService(Type serviceType)
        {
            object service = null;
 
            if (serviceType == typeof(IReferenceService))
                service = new ActivityCodeDomReferenceService(this.serializationManager.GetService(serviceType) as IReferenceService);
 
            if (serviceType == typeof(IServiceContainer))
            {
                service = serializationManager.GetService(serviceType);
 
                if (service == null)
                {
                    service = serviceContainer;
                }
            }
 
            // If we haven't provded the service, try the serialization manager we wrap
            if (service == null)
                service = this.serializationManager.GetService(serviceType);
 
            // Last ditch effort, see if our consumer had added the service
            if (service == null)
                service = serviceContainer.GetService(serviceType);
 
            return service;
        }
 
        // work around : PD7's PrimitiveCodeDomSerializer does not handle well strings bigger than 200 characters, 
        //       we push our own version to fix it.
        public object GetSerializer(Type objectType, Type serializerType)
        {
            if (objectType == typeof(string))
            {
                return PrimitiveCodeDomSerializer.Default;
            }
            else if (objectType != null && TypeProvider.IsAssignable(typeof(ICollection<String>), objectType) && !objectType.IsArray && serializerType == typeof(CodeDomSerializer))
            {
                PropertyDescriptor pd = Context[typeof(PropertyDescriptor)] as PropertyDescriptor;
                if (pd != null)
                {
                    if (string.Equals(pd.Name, "SynchronizationHandles", StringComparison.Ordinal) && TypeProvider.IsAssignable(typeof(Activity), pd.ComponentType))
                        return new SynchronizationHandlesCodeDomSerializer();
                }
                else
                {
                    // If property descriptor is not available, we then look at the expression context.
                    ExpressionContext context = Context[typeof(ExpressionContext)] as ExpressionContext;
                    if (context != null && context.Expression is CodePropertyReferenceExpression &&
                        string.Equals(((CodePropertyReferenceExpression)context.Expression).PropertyName, "SynchronizationHandles", StringComparison.Ordinal))
                        return new SynchronizationHandlesCodeDomSerializer();
                }
            }
 
            object serializer = this.serializationManager.GetSerializer(objectType, serializerType);
            if (!UseUserDefinedSerializer(objectType, serializerType))
                serializer = new SerializableTypeCodeDomSerializer(serializer as CodeDomSerializer);
 
            return serializer;
        }
 
        // We add this custom serializable to handler serializable types so they don't go into the resources
        // as majority of our types will be serializable per WinOE runtime requirements.
        // Note: we will not overwrite any custom serializer behaviors.  If the serializer does not come
        // from the Sytem.ComponentModel.dll, we will not overwrite it.
        private bool UseUserDefinedSerializer(Type objectType, Type serializerType)
        {
            if (objectType == null || serializerType == null)
                return true;
 
            //If objectType is not serializable or we are not looking for codedomserializer then use user defined serializer
            if (!objectType.IsSerializable || serializerType != typeof(CodeDomSerializer))
                return true;
 
            //For primitives always honor user defined serializer
            if (objectType.IsPrimitive || objectType.IsEnum || objectType == typeof(string) || typeof(Activity).IsAssignableFrom(objectType))
                return true;
 
            //If user has defined instance descriptor then we always serialize to a create expression so we honor
            //user defined serializer
            TypeConverter converter = TypeDescriptor.GetConverter(objectType);
            if (converter != null && converter.CanConvertTo(typeof(InstanceDescriptor)))
                return true;
 
            //If the serializer is a custom codedom serializer ie it does not come from our or system  assembly
            //defining codedomserializer then always honor user's serializer as user needs a way to override the
            //serializartion process
            object serializer = this.serializationManager.GetSerializer(objectType, serializerType);
            if (serializer.GetType().Assembly != typeof(CodeDomSerializer).Assembly &&
                serializer.GetType().Assembly != Assembly.GetExecutingAssembly() &&
                serializer.GetType().Assembly != Assembly.Load(AssemblyRef.ActivitiesAssemblyRef))
                return true;
 
            //Special case for UI objects they need to always come from the resource only if we are not compiling
            Activity activity = this.serializationManager.Context[typeof(Activity)] as Activity;
            if (activity != null && activity.Site != null && activity.Site.Container != null &&
                objectType.Namespace != null && objectType.Namespace.Equals(typeof(System.Drawing.Image).Namespace))
                return true;
 
            return false;
        }
 
        public object GetInstance(string name)
        {
            return this.serializationManager.GetInstance(name);
        }
 
        public void AddSerializationProvider(IDesignerSerializationProvider provider)
        {
            this.serializationManager.AddSerializationProvider(provider);
        }
 
        public void RemoveSerializationProvider(IDesignerSerializationProvider provider)
        {
            this.serializationManager.RemoveSerializationProvider(provider);
        }
 
        public void ReportError(object errorInformation)
        {
            this.serializationManager.ReportError(errorInformation);
        }
        public ContextStack Context
        {
            get
            {
                return this.serializationManager.Context;
            }
        }
 
        public event ResolveNameEventHandler ResolveName
        {
            add
            {
                this.resolveNameEventHandler += value;
            }
            remove
            {
                this.resolveNameEventHandler -= value;
            }
        }
 
        public PropertyDescriptorCollection Properties
        {
            get
            {
                return this.serializationManager.Properties;
            }
        }
 
 
        public Type GetType(string typeName)
        {
            Type type = this.serializationManager.GetType(typeName);
            if (type == null)
            {
                // if this is a design time time
                ITypeProvider typeProvider = this.GetService(typeof(ITypeProvider)) as ITypeProvider;
                if (typeProvider != null)
                    type = typeProvider.GetType(typeName);
            }
 
            return type;
        }
 
        protected IDesignerSerializationManager SerializationManager
        {
            get
            {
                return this.serializationManager;
            }
 
            set
            {
                this.serializationManager = value;
            }
        }
    }
    #endregion
 
}