File: AuthoringOM\Serializer\WorkflowMarkupSerializer.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
namespace System.Workflow.ComponentModel.Serialization
{
    using System;
    using System.IO;
    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.ComponentModel.Design.Serialization;
    using System.Collections;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics;
    using System.Text;
    using System.Globalization;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.ComponentModel.Serialization;
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Collections.ObjectModel;
    using System.Drawing;
    using System.Diagnostics.CodeAnalysis;
 
    #region Class WorkflowMarkupSerializer
 
    //Main serialization class for persisting the XOML
    [DefaultSerializationProvider(typeof(WorkflowMarkupSerializationProvider))]
    public class WorkflowMarkupSerializer
    {
        // x:Class & x:Code property.  public so it can be set from outside.
        public static readonly DependencyProperty XClassProperty = DependencyProperty.RegisterAttached("XClass", typeof(string), typeof(WorkflowMarkupSerializer), new PropertyMetadata(DependencyPropertyOptions.Metadata, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }));
        public static readonly DependencyProperty XCodeProperty = DependencyProperty.RegisterAttached("XCode", typeof(CodeTypeMemberCollection), typeof(WorkflowMarkupSerializer), new PropertyMetadata(DependencyPropertyOptions.Metadata, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }));
 
        public static readonly DependencyProperty EventsProperty = DependencyProperty.RegisterAttached("Events", typeof(Hashtable), typeof(WorkflowMarkupSerializer), new PropertyMetadata(null, new Attribute[] { new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }));
        public static readonly DependencyProperty ClrNamespacesProperty = DependencyProperty.RegisterAttached("ClrNamespaces", typeof(List<String>), typeof(WorkflowMarkupSerializer), new PropertyMetadata(null, new Attribute[] { new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }));
 
        // This collection is populated from config under System.Workflow.Compiler section and then
        // a few "hard coded" UNauthorized types are added to it
        private static volatile ReadOnlyCollection<AuthorizedType> StaticAuthorizedTypes;
        private static object StaticAuthTypesLockObject = new object();
 
        #region Public Methods
        public object Deserialize(XmlReader reader)
        {
            if (reader == null)
                throw new ArgumentNullException("reader");
 
            DesignerSerializationManager designerSerializationManager = new DesignerSerializationManager();
            using (designerSerializationManager.CreateSession())
            {
                return Deserialize(designerSerializationManager, reader);
            }
        }
 
        public object Deserialize(IDesignerSerializationManager serializationManager, XmlReader reader)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (reader == null)
                throw new ArgumentNullException("reader");
 
            // If SerializerTypeChecking is enabled, initialize it.
            if (!AppSettings.DisableXOMLSerializerTypeChecking)
            {
                WorkflowMarkupSerializer.GetAuthorizedTypes();
                SerializerTypeAuthorizerClass typeAuthorizer = new SerializerTypeAuthorizerClass(WorkflowMarkupSerializer.StaticAuthorizedTypes);
                WorkflowMarkupSerializationHelpers.SerializationTypeAuthorizer = typeAuthorizer;
            }
 
            WorkflowMarkupSerializationManager markupSerializationManager = serializationManager as WorkflowMarkupSerializationManager;
            if (markupSerializationManager == null)
                markupSerializationManager = new WorkflowMarkupSerializationManager(serializationManager);
 
            string fileName = markupSerializationManager.Context[typeof(string)] as string;
            if (fileName == null)
                fileName = String.Empty;
 
            markupSerializationManager.FoundDefTag += delegate(object sender, WorkflowMarkupElementEventArgs eventArgs)
            {
                if (eventArgs.XmlReader.LookupNamespace(eventArgs.XmlReader.Prefix) == StandardXomlKeys.Definitions_XmlNs)
                    WorkflowMarkupSerializationHelpers.ProcessDefTag(markupSerializationManager, eventArgs.XmlReader, markupSerializationManager.Context.Current as Activity, false, fileName);
            };
            object obj = DeserializeXoml(markupSerializationManager, reader);
 
            // Copy the mappingPI to schedule user data
            Activity rootActivity = obj as Activity;
            if (rootActivity != null)
            {
                List<String> clrMappings = rootActivity.GetValue(WorkflowMarkupSerializer.ClrNamespacesProperty) as List<String>;
                if (clrMappings == null)
                {
                    clrMappings = new List<String>();
                    rootActivity.SetValue(WorkflowMarkupSerializer.ClrNamespacesProperty, clrMappings);
                }
 
                foreach (WorkflowMarkupSerializerMapping mapping in markupSerializationManager.ClrNamespaceBasedMappings.Values)
                    clrMappings.Add(mapping.ClrNamespace);
 
                rootActivity.SetValue(ActivityCodeDomSerializer.MarkupFileNameProperty, fileName);
 
                // If Name is not set and there is an XClass, set the name to that.
                if ((string.IsNullOrEmpty(rootActivity.Name) || rootActivity.Name == rootActivity.GetType().Name) && !string.IsNullOrEmpty(rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string))
                {
                    string name = rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string;
                    if (name.Contains("."))
                        rootActivity.Name = name.Substring(name.LastIndexOf('.') + 1);
                    else
                        rootActivity.Name = name;
                }
            }
 
            return obj;
        }
 
        private object DeserializeXoml(WorkflowMarkupSerializationManager serializationManager, XmlReader xmlReader)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (xmlReader == null)
                throw new ArgumentNullException("xmlReader");
 
            Object obj = null;
            //xmlReader.WhitespaceHandling = WhitespaceHandling.None;
            serializationManager.WorkflowMarkupStack.Push(xmlReader);
 
            try
            {
                // 
                while (xmlReader.Read() && xmlReader.NodeType != XmlNodeType.Element && xmlReader.NodeType != XmlNodeType.ProcessingInstruction);
                if (xmlReader.EOF)
                    return null;
                obj = DeserializeObject(serializationManager, xmlReader);
 
                // Read until the end of the xml stream i.e past the </XomlDocument> tag. 
                // If there are any exceptions log them as errors.
                while (xmlReader.Read() && !xmlReader.EOF);
            }
            catch (XmlException xmlException)
            {
                throw new WorkflowMarkupSerializationException(xmlException.Message, xmlException, xmlException.LineNumber, xmlException.LinePosition);
            }
            catch (Exception e)
            {
                throw CreateSerializationError(e, xmlReader);
            }
            finally
            {
                serializationManager.WorkflowMarkupStack.Pop();
            }
 
            return obj;
        }
 
        public void Serialize(XmlWriter writer, object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (writer == null)
                throw new ArgumentNullException("writer");
 
            DesignerSerializationManager designerSerializationManager = new DesignerSerializationManager();
            using (designerSerializationManager.CreateSession())
            {
                Serialize(designerSerializationManager, writer, obj);
            }
        }
 
        public void Serialize(IDesignerSerializationManager serializationManager, XmlWriter writer, object obj)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (writer == null)
                throw new ArgumentNullException("writer");
 
            WorkflowMarkupSerializationManager markupSerializationManager = serializationManager as WorkflowMarkupSerializationManager;
            if (markupSerializationManager == null)
                markupSerializationManager = new WorkflowMarkupSerializationManager(serializationManager);
 
            StringWriter xomlStringWriter = new StringWriter(CultureInfo.InvariantCulture);
            XmlWriter xmlWriter = Helpers.CreateXmlWriter(xomlStringWriter);
            markupSerializationManager.WorkflowMarkupStack.Push(xmlWriter);
            markupSerializationManager.WorkflowMarkupStack.Push(xomlStringWriter);
 
            try
            {
                SerializeObject(markupSerializationManager, obj, xmlWriter);
            }
            finally
            {
                xmlWriter.Close();
                writer.WriteRaw(xomlStringWriter.ToString());
                writer.Flush();
                markupSerializationManager.WorkflowMarkupStack.Pop();
                markupSerializationManager.WorkflowMarkupStack.Pop();
            }
        }
        #endregion
 
        #region Protected Methods (Non-overridable)
        internal object DeserializeObject(WorkflowMarkupSerializationManager serializationManager, XmlReader reader)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (reader == null)
                throw new ArgumentNullException("reader");
 
            object obj = null;
            try
            {
                serializationManager.WorkflowMarkupStack.Push(reader);
 
                AdvanceReader(reader);
                if (reader.NodeType != XmlNodeType.Element)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFound), reader));
                }
                else
                {
                    // Lets ignore the Definition tags if nobody is interested
                    //
                    string decodedName = XmlConvert.DecodeName(reader.LocalName);
                    XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(decodedName, reader.LookupNamespace(reader.Prefix));
                    if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal) &&
                        !IsMarkupExtension(xmlQualifiedName) &&
                        !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName))
                    {
                        int initialDepth = reader.Depth;
                        serializationManager.FireFoundDefTag(new WorkflowMarkupElementEventArgs(reader));
                        if ((initialDepth + 1) < reader.Depth)
                        {
                            while (reader.Read() && (initialDepth + 1) < reader.Depth);
                        }
                    }
                    else
                    {
                        obj = CreateInstance(serializationManager, xmlQualifiedName, reader);
                        reader.MoveToElement();
                        if (obj != null)
                        {
                            serializationManager.ContextPush(obj);
                            try
                            {
                                DeserializeContents(serializationManager, obj, reader);
                            }
                            finally
                            {
                                Debug.Assert(serializationManager.Context.Current == obj, "Serializer did not remove an object it pushed into stack.");
                                serializationManager.ContextPop();
                            }
                        }
                    }
                }
            }
            finally
            {
                serializationManager.WorkflowMarkupStack.Pop();
            }
            return obj;
        }
 
        private void DeserializeContents(WorkflowMarkupSerializationManager serializationManager, object obj, XmlReader reader)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (reader == null)
                throw new ArgumentNullException("reader");
 
            if (reader.NodeType != XmlNodeType.Element)
                return;
 
            // get the serializer
            WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
            if (serializer == null)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader));
                return;
            }
 
            try
            {
                serializer.OnBeforeDeserialize(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
            }
 
            bool isEmptyElement = reader.IsEmptyElement;
            string elementNamespace = reader.NamespaceURI;
 
            List<PropertyInfo> props = new List<PropertyInfo>();
            List<EventInfo> events = new List<EventInfo>();
            // Add the extended properties for primitive types
            if (obj.GetType().IsPrimitive || obj.GetType() == typeof(string) || obj.GetType() == typeof(decimal) ||
                obj.GetType().IsEnum || obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) ||
                obj.GetType() == typeof(Guid))
            {
                props.AddRange(serializationManager.GetExtendedProperties(obj));
            }
            else
            {
                try
                {
                    props.AddRange(serializer.GetProperties(serializationManager, obj));
                    props.AddRange(serializationManager.GetExtendedProperties(obj));
                    events.AddRange(serializer.GetEvents(serializationManager, obj));
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType(), e.Message), e, reader));
                    return;
                }
            }
            //First we try to deserialize simple properties
            if (reader.HasAttributes)
            {
                while (reader.MoveToNextAttribute())
                {
                    // 
                    if (reader.LocalName.Equals("xmlns", StringComparison.Ordinal) || reader.Prefix.Equals("xmlns", StringComparison.Ordinal))
                        continue;
 
                    //
                    XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix));
                    if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal) &&
                        !IsMarkupExtension(xmlQualifiedName) &&
                        !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, props, xmlQualifiedName) &&
                        !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName))
                    {
                        serializationManager.FireFoundDefTag(new WorkflowMarkupElementEventArgs(reader));
                        continue;
                    }
 
                    //For simple properties we assume that if . indicates
                    string propName = XmlConvert.DecodeName(reader.LocalName);
                    string propVal = reader.Value;
                    DependencyProperty dependencyProperty = ResolveDependencyProperty(serializationManager, reader, obj, propName);
                    if (dependencyProperty != null)
                    {
                        serializationManager.ContextPush(dependencyProperty);
                        try
                        {
                            if (dependencyProperty.IsEvent)
                                DeserializeEvent(serializationManager, reader, obj, propVal);
                            else
                                DeserializeSimpleProperty(serializationManager, reader, obj, propVal);
                        }
                        finally
                        {
                            Debug.Assert(serializationManager.Context.Current == dependencyProperty, "Serializer did not remove an object it pushed into stack.");
                            serializationManager.ContextPop();
                        }
                    }
                    else
                    {
                        PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(props, propName);
                        if (property != null)
                        {
                            serializationManager.ContextPush(property);
                            try
                            {
                                DeserializeSimpleProperty(serializationManager, reader, obj, propVal);
                            }
                            finally
                            {
                                Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack.");
                                serializationManager.ContextPop();
                            }
                        }
                        else
                        {
                            EventInfo evt = WorkflowMarkupSerializer.LookupEvent(events, propName);
                            if (events != null && evt != null)
                            {
                                serializationManager.ContextPush(evt);
                                try
                                {
                                    DeserializeEvent(serializationManager, reader, obj, propVal);
                                }
                                finally
                                {
                                    Debug.Assert((EventInfo)serializationManager.Context.Current == evt, "Serializer did not remove an object it pushed into stack.");
                                    serializationManager.ContextPop();
                                }
                            }
                            else
                                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNoMemberFound, new object[] { propName, obj.GetType().FullName }), reader));
                        }
                    }
                }
            }
 
            try
            {
                serializer.OnBeforeDeserializeContents(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
            }
 
            //Now deserialize compound properties
            try
            {
                serializer.ClearChildren(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType(), e.Message), e, reader));
                return;
            }
 
            using (ContentProperty contentProperty = new ContentProperty(serializationManager, serializer, obj))
            {
                List<ContentInfo> contents = new List<ContentInfo>();
                if (!isEmptyElement)
                {
                    reader.MoveToElement();
                    int initialDepth = reader.Depth;
                    XmlQualifiedName extendedPropertyQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix));
                    do
                    {
                        // Extended property should be deserialized, this is required for primitive types which have extended property as children
                        // We should  not ignore 
                        if (extendedPropertyQualifiedName != null && !ExtendedPropertyInfo.IsExtendedProperty(serializationManager, extendedPropertyQualifiedName))
                        {
                            extendedPropertyQualifiedName = null;
                            continue;
                        }
                        // this will make it to skip all the nodes
                        if ((initialDepth + 1) < reader.Depth)
                        {
                            bool unnecessaryXmlFound = false;
                            while (reader.Read() && ((initialDepth + 1) < reader.Depth))
                            {
                                // Ignore comments and whitespaces
                                if (reader.NodeType != XmlNodeType.Comment && reader.NodeType != XmlNodeType.Whitespace && !unnecessaryXmlFound)
                                {
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFoundForType, obj.GetType().FullName), reader));
                                    unnecessaryXmlFound = true;
                                }
                            }
                        }
 
                        //Push all the PIs into stack so that they are available for type resolution
                        AdvanceReader(reader);
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            //We should only support A.B syntax for compound properties, all others are treated as content
                            XmlQualifiedName xmlQualifiedName = new XmlQualifiedName(reader.LocalName, reader.LookupNamespace(reader.Prefix));
                            int index = reader.LocalName.IndexOf('.');
                            if (index > 0 || ExtendedPropertyInfo.IsExtendedProperty(serializationManager, xmlQualifiedName))
                            {
                                string propertyName = reader.LocalName.Substring(reader.LocalName.IndexOf('.') + 1);
                                PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(props, propertyName);
                                DependencyProperty dependencyProperty = ResolveDependencyProperty(serializationManager, reader, obj, reader.LocalName);
                                if (dependencyProperty == null && property == null)
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidElementFoundForType, reader.LocalName, obj.GetType().FullName), reader));
                                else if (dependencyProperty != null)
                                {
                                    PropertyInfo prop = WorkflowMarkupSerializer.LookupProperty(props, dependencyProperty.Name);
                                    //Deserialize the dynamic property
                                    serializationManager.ContextPush(dependencyProperty);
                                    try
                                    {
                                        DeserializeCompoundProperty(serializationManager, reader, obj);
                                    }
                                    finally
                                    {
                                        Debug.Assert(serializationManager.Context.Current == dependencyProperty, "Serializer did not remove an object it pushed into stack.");
                                        serializationManager.ContextPop();
                                    }
                                }
                                else if (property != null)
                                {
                                    //Deserialize the compound property
                                    serializationManager.ContextPush(property);
                                    try
                                    {
                                        DeserializeCompoundProperty(serializationManager, reader, obj);
                                    }
                                    finally
                                    {
                                        Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack.");
                                        serializationManager.ContextPop();
                                    }
                                }
                            }
                            else
                            {
                                //Deserialize the children
                                int lineNumber = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1;
                                int linePosition = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1;
                                object obj2 = DeserializeObject(serializationManager, reader);
                                if (obj2 != null)
                                {
                                    obj2 = GetValueFromMarkupExtension(serializationManager, obj2);
                                    if (obj2 != null && obj2.GetType() == typeof(string) && ((string)obj2).StartsWith("{}", StringComparison.Ordinal))
                                        obj2 = ((string)obj2).Substring(2);
                                    contents.Add(new ContentInfo(obj2, lineNumber, linePosition));
                                }
                            }
                        }
                        else if (reader.NodeType == XmlNodeType.Text && contentProperty.Property != null)
                        {
                            //If we read the string then we should not advance the reader further instead break
                            int lineNumber = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1;
                            int linePosition = (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1;
                            contents.Add(new ContentInfo(reader.ReadString(), lineNumber, linePosition));
                            if (initialDepth >= reader.Depth)
                                break;
                        }
                        else
                        {
                            if (reader.NodeType == XmlNodeType.Entity ||
                                reader.NodeType == XmlNodeType.Text ||
                                reader.NodeType == XmlNodeType.CDATA)
                                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_InvalidDataFound, reader.Value.Trim(), obj.GetType().FullName), reader));
                        }
                    } while (reader.Read() && initialDepth < reader.Depth);
                }
                //Make sure that we set contents
                contentProperty.SetContents(contents);
            }
            try
            {
                serializer.OnAfterDeserialize(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
            }
        }
 
        internal void SerializeObject(WorkflowMarkupSerializationManager serializationManager, object obj, XmlWriter writer)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (writer == null)
                throw new ArgumentNullException("writer");
 
            try
            {
                serializationManager.WorkflowMarkupStack.Push(writer);
                using (new SafeXmlNodeWriter(serializationManager, obj, null, XmlNodeType.Element))
                {
                    DictionaryEntry? entry = null;
                    if (serializationManager.WorkflowMarkupStack[typeof(DictionaryEntry)] != null)
                        entry = (DictionaryEntry)serializationManager.WorkflowMarkupStack[typeof(DictionaryEntry)];
 
                    // To handle the case when the key and value are same in the dictionary
                    bool key = entry.HasValue && ((!entry.Value.GetType().IsValueType && entry.Value.Key == entry.Value.Value && entry.Value.Value == obj) ||
                                                    (entry.Value.GetType().IsValueType && entry.Value.Key.Equals(entry.Value.Value) && entry.Value.Value.Equals(obj))) &&
                                                    serializationManager.SerializationStack.Contains(obj);
                    if (key || !serializationManager.SerializationStack.Contains(obj))
                    {
                        serializationManager.ContextPush(obj);
                        serializationManager.SerializationStack.Push(obj);
                        try
                        {
                            SerializeContents(serializationManager, obj, writer, key);
                        }
                        finally
                        {
                            Debug.Assert(serializationManager.Context.Current == obj, "Serializer did not remove an object it pushed into stack.");
                            serializationManager.ContextPop();
                            serializationManager.SerializationStack.Pop();
                        }
                    }
                    else
                        throw new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerStackOverflow, obj.ToString(), obj.GetType().FullName), 0, 0);
                }
            }
            finally
            {
                serializationManager.WorkflowMarkupStack.Pop();
            }
        }
 
        internal void SerializeContents(WorkflowMarkupSerializationManager serializationManager, object obj, XmlWriter writer, bool dictionaryKey)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (writer == null)
                throw new ArgumentNullException("writer");
 
            WorkflowMarkupSerializer serializer = null;
            try
            {
                //Now get the serializer to persist the properties, if the serializer is not found then we dont serialize the properties
                serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
 
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
 
            }
 
            if (serializer == null)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, obj.GetType().FullName)));
                return;
            }
 
            try
            {
                serializer.OnBeforeSerialize(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
            }
 
            Hashtable allProperties = new Hashtable();
            ArrayList complexProperties = new ArrayList();
 
            IDictionary<DependencyProperty, object> dependencyProperties = null;
            List<PropertyInfo> properties = new List<PropertyInfo>();
            List<EventInfo> events = new List<EventInfo>();
            Hashtable designTimeTypeNames = null;
 
            // Serialize the extended properties for primitive types also
            if (obj.GetType().IsPrimitive || obj.GetType() == typeof(string) || obj.GetType() == typeof(decimal) ||
                obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) || obj.GetType().IsEnum ||
                obj.GetType() == typeof(Guid))
            {
                if (obj.GetType() == typeof(char) || obj.GetType() == typeof(byte) ||
                    obj.GetType() == typeof(System.Int16) || obj.GetType() == typeof(decimal) ||
                    obj.GetType() == typeof(DateTime) || obj.GetType() == typeof(TimeSpan) ||
                    obj.GetType().IsEnum || obj.GetType() == typeof(Guid))
                {
                    //These non CLS-compliant are not supported in the XmlWriter 
                    if ((obj.GetType() != typeof(char)) || (char)obj != '\0')
                    {
                        //These non CLS-compliant are not supported in the XmlReader 
                        string stringValue = String.Empty;
                        if (obj.GetType() == typeof(DateTime))
                        {
                            stringValue = ((DateTime)obj).ToString("o", CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            TypeConverter typeConverter = TypeDescriptor.GetConverter(obj.GetType());
                            if (typeConverter != null && typeConverter.CanConvertTo(typeof(string)))
                                stringValue = typeConverter.ConvertTo(null, CultureInfo.InvariantCulture, obj, typeof(string)) as string;
                            else
                                stringValue = Convert.ToString(obj, CultureInfo.InvariantCulture);
                        }
 
                        writer.WriteValue(stringValue);
                    }
                }
                else if (obj.GetType() == typeof(string))
                {
                    string attribValue = obj as string;
                    attribValue = attribValue.Replace('\0', ' ');
                    if (!(attribValue.StartsWith("{", StringComparison.Ordinal) && attribValue.EndsWith("}", StringComparison.Ordinal)))
                        writer.WriteValue(attribValue);
                    else
                        writer.WriteValue("{}" + attribValue);
                }
                else
                {
                    writer.WriteValue(obj);
                }
                // For Key properties, we don;t want to get the extended properties
                if (!dictionaryKey)
                    properties.AddRange(serializationManager.GetExtendedProperties(obj));
            }
            else
            {
                // Serialize properties
                //We first get all the properties, once we have them all, we start distinguishing between
                //simple and complex properties, the reason for that is XmlWriter needs to write attributes
                //first and elements later
 
                // Dependency events are treated as the same as dependency properties.
 
 
                try
                {
                    if (obj is DependencyObject && ((DependencyObject)obj).UserData.Contains(UserDataKeys.DesignTimeTypeNames))
                        designTimeTypeNames = ((DependencyObject)obj).UserData[UserDataKeys.DesignTimeTypeNames] as Hashtable;
                    dependencyProperties = serializer.GetDependencyProperties(serializationManager, obj);
                    properties.AddRange(serializer.GetProperties(serializationManager, obj));
                    // For Key properties, we don;t want to get the extended properties
                    if (!dictionaryKey)
                        properties.AddRange(serializationManager.GetExtendedProperties(obj));
                    events.AddRange(serializer.GetEvents(serializationManager, obj));
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                    return;
                }
            }
            if (dependencyProperties != null)
            {
                // For attached properties that does not have a corresponding real property on the object, if the value is a design time
                // type, it may not be set through dependency property SetValue, therefore will not be present in the dependencyProperties
                // collection, we'll have to get the dependency property object ourselves.
                if (designTimeTypeNames != null)
                {
                    foreach (object key in designTimeTypeNames.Keys)
                    {
                        DependencyProperty dependencyProperty = key as DependencyProperty;
                        if (dependencyProperty != null && !dependencyProperties.ContainsKey(dependencyProperty))
                            dependencyProperties.Add(dependencyProperty, designTimeTypeNames[dependencyProperty]);
                    }
                }
 
                // Add all dependency properties to the master collection.
                foreach (DependencyProperty dependencyProperty in dependencyProperties.Keys)
                {
                    string propertyName = String.Empty;
                    if (dependencyProperty.IsAttached)
                    {
                        string prefix = String.Empty;
                        XmlQualifiedName qualifiedName = serializationManager.GetXmlQualifiedName(dependencyProperty.OwnerType, out prefix);
                        propertyName = qualifiedName.Name + "." + dependencyProperty.Name;
                    }
                    else
                    {
                        propertyName = dependencyProperty.Name;
                    }
 
                    if (dependencyProperty.IsAttached || !dependencyProperty.DefaultMetadata.IsMetaProperty)
                        allProperties.Add(propertyName, dependencyProperty);
                }
            }
 
            if (properties != null)
            {
                foreach (PropertyInfo propInfo in properties)
                {
                    // Do not serialize properties that have corresponding dynamic properties.
                    if (propInfo != null && !allProperties.ContainsKey(propInfo.Name))
                        allProperties.Add(propInfo.Name, propInfo);
                }
            }
 
            if (events != null)
            {
                foreach (EventInfo eventInfo in events)
                {
                    // Do not serialize events that have corresponding dynamic properties.
                    if (eventInfo != null && !allProperties.ContainsKey(eventInfo.Name))
                        allProperties.Add(eventInfo.Name, eventInfo);
                }
            }
 
            using (ContentProperty contentProperty = new ContentProperty(serializationManager, serializer, obj))
            {
                foreach (object propertyObj in allProperties.Values)
                {
                    string propertyName = String.Empty;
                    object propertyValue = null;
                    Type propertyInfoType = null;
 
                    try
                    {
                        if (propertyObj is PropertyInfo)
                        {
                            PropertyInfo property = propertyObj as PropertyInfo;
 
                            // If the property has parameters we can not serialize it , we just move on.
                            ParameterInfo[] indexParameters = property.GetIndexParameters();
                            if (indexParameters != null && indexParameters.Length > 0)
                                continue;
 
                            propertyName = property.Name;
                            propertyValue = null;
                            if (property.CanRead)
                            {
                                propertyValue = property.GetValue(obj, null);
                                if (propertyValue == null && TypeProvider.IsAssignable(typeof(Type), property.PropertyType))
                                {
                                    // See if we have a design time value for the property
                                    DependencyProperty dependencyProperty = DependencyProperty.FromName(property.Name, property.ReflectedType);
                                    if (dependencyProperty != null)
                                        propertyValue = Helpers.GetDesignTimeTypeName(obj, dependencyProperty);
 
                                    if (propertyValue == null)
                                    {
                                        string key = property.ReflectedType.FullName + "." + property.Name;
                                        propertyValue = Helpers.GetDesignTimeTypeName(obj, key);
                                    }
                                    if (propertyValue != null)
                                        propertyValue = new TypeExtension((string)propertyValue);
                                }
                            }
                            propertyInfoType = property.PropertyType;
                        }
                        else if (propertyObj is EventInfo)
                        {
                            EventInfo evt = propertyObj as EventInfo;
                            propertyName = evt.Name;
                            propertyValue = WorkflowMarkupSerializationHelpers.GetEventHandlerName(obj, evt.Name);
                            if ((propertyValue == null || (propertyValue is string && string.IsNullOrEmpty((string)propertyValue)))
                                && obj is DependencyObject)
                            {
                                // The object is not created through deserialization, we should check to see if the delegate is 
                                // created and added to list.  We can only serialize the handler if its target type is the same
                                // as the activity type that's be designed.
                                DependencyProperty dependencyProperty = DependencyProperty.FromName(propertyName, obj.GetType());
                                if (dependencyProperty != null)
                                {
                                    Activity activity = serializationManager.Context[typeof(Activity)] as Activity;
                                    Delegate handler = ((DependencyObject)obj).GetHandler(dependencyProperty) as Delegate;
                                    if (handler != null && activity != null && TypeProvider.Equals(handler.Target.GetType(), Helpers.GetRootActivity(activity).GetType()))
                                        propertyValue = handler;
                                }
                            }
                            propertyInfoType = evt.EventHandlerType;
                        }
                        else if (propertyObj is DependencyProperty)
                        {
                            DependencyProperty dependencyProperty = propertyObj as DependencyProperty;
                            propertyName = dependencyProperty.Name;
                            propertyValue = dependencyProperties[dependencyProperty];
                            propertyInfoType = dependencyProperty.PropertyType;
                        }
                    }
                    catch (Exception e)
                    {
                        while (e is TargetInvocationException && e.InnerException != null)
                            e = e.InnerException;
 
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerPropertyGetFailed, new object[] { propertyName, obj.GetType().FullName, e.Message })));
                        continue;
                    }
 
                    if (propertyObj is PropertyInfo && contentProperty.Property == (PropertyInfo)propertyObj)
                        continue;
 
                    Type propertyValueType = null;
                    if (propertyValue != null)
                    {
                        propertyValue = GetMarkupExtensionFromValue(propertyValue);
                        propertyValueType = propertyValue.GetType();
                    }
                    else if (propertyObj is PropertyInfo)
                    {
                        propertyValue = new NullExtension();
                        propertyValueType = propertyValue.GetType();
                        Attribute[] attributes = Attribute.GetCustomAttributes(propertyObj as PropertyInfo, typeof(DefaultValueAttribute), true);
                        if (attributes.Length > 0)
                        {
                            DefaultValueAttribute defaultValueAttr = attributes[0] as DefaultValueAttribute;
                            if (defaultValueAttr.Value == null)
                                propertyValue = null;
                        }
                    }
                    if (propertyValue != null)
                        propertyValueType = propertyValue.GetType();
 
                    //Now get the serializer to persist the properties, if the serializer is not found then we dont serialize the properties
                    serializationManager.ContextPush(propertyObj);
                    WorkflowMarkupSerializer propValueSerializer = null;
                    try
                    {
                        propValueSerializer = serializationManager.GetSerializer(propertyValueType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                    }
                    catch (Exception e)
                    {
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                        serializationManager.ContextPop();
                        continue;
                    }
                    if (propValueSerializer == null)
                    {
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, propertyValueType.FullName)));
                        serializationManager.ContextPop();
                        continue;
                    }
 
                    // ask serializer if we can serialize
                    try
                    {
                        if (propValueSerializer.ShouldSerializeValue(serializationManager, propertyValue))
                        {
                            //NOTE: THE FOLLOWING CONDITION ABOUT propertyInfoType != typeof(object) is VALID AS WE SHOULD NOT SERIALIZE A PROPERTY OF TYPE OBJECT TO STRING
                            //IF WE DO THAT THEN WE DO NOT KNOWN WHAT WAS THE TYPE OF ORIGINAL OBJECT AND SERIALIZER WONT BE ABLE TO GET THE STRING BACK INTO THE CORRECT TYPE,
                            //AS THE TYPE INFORMATION IS LOST
                            if (propValueSerializer.CanSerializeToString(serializationManager, propertyValue) && propertyInfoType != typeof(object))
                            {
                                using (new SafeXmlNodeWriter(serializationManager, obj, propertyObj, XmlNodeType.Attribute))
                                {
                                    //This is a work around to special case the markup extension serializer as it writes to the stream using writer
                                    if (propValueSerializer is MarkupExtensionSerializer)
                                    {
                                        propValueSerializer.SerializeToString(serializationManager, propertyValue);
                                    }
                                    else
                                    {
                                        string stringValue = propValueSerializer.SerializeToString(serializationManager, propertyValue);
                                        if (!string.IsNullOrEmpty(stringValue))
                                        {
                                            stringValue = stringValue.Replace('\0', ' ');
                                            if (propertyValue is MarkupExtension || !(stringValue.StartsWith("{", StringComparison.Ordinal) && stringValue.EndsWith("}", StringComparison.Ordinal)))
                                                writer.WriteString(stringValue);
                                            else
                                                writer.WriteString("{}" + stringValue);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                complexProperties.Add(propertyObj);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNoSerializeLogic, new object[] { propertyName, obj.GetType().FullName }), e));
                    }
                    finally
                    {
                        Debug.Assert(serializationManager.Context.Current == propertyObj, "Serializer did not remove an object it pushed into stack.");
                        serializationManager.ContextPop();
                    }
                }
 
                try
                {
                    serializer.OnBeforeSerializeContents(serializationManager, obj);
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                    return;
                }
 
                // serialize compound properties as child elements of the current node.
                foreach (object propertyObj in complexProperties)
                {
                    // get value and check for null
                    string propertyName = String.Empty;
                    object propertyValue = null;
                    Type ownerType = null;
                    bool isReadOnly = false;
 
                    try
                    {
                        if (propertyObj is PropertyInfo)
                        {
                            PropertyInfo property = propertyObj as PropertyInfo;
                            propertyName = property.Name;
                            propertyValue = property.CanRead ? property.GetValue(obj, null) : null;
                            ownerType = obj.GetType();
                            isReadOnly = (!property.CanWrite);
                        }
                        else if (propertyObj is DependencyProperty)
                        {
                            DependencyProperty dependencyProperty = propertyObj as DependencyProperty;
                            propertyName = dependencyProperty.Name;
                            propertyValue = dependencyProperties[dependencyProperty];
                            ownerType = dependencyProperty.OwnerType;
                            isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly);
                        }
                    }
                    catch (Exception e)
                    {
                        while (e is TargetInvocationException && e.InnerException != null)
                            e = e.InnerException;
 
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerPropertyGetFailed, propertyName, ownerType.FullName, e.Message)));
                        continue;
                    }
 
                    if (propertyObj is PropertyInfo && (PropertyInfo)propertyObj == contentProperty.Property)
                        continue;
 
                    if (propertyValue != null)
                    {
                        propertyValue = GetMarkupExtensionFromValue(propertyValue);
 
                        WorkflowMarkupSerializer propValueSerializer = serializationManager.GetSerializer(propertyValue.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                        if (propValueSerializer != null)
                        {
                            using (new SafeXmlNodeWriter(serializationManager, obj, propertyObj, XmlNodeType.Element))
                            {
                                if (isReadOnly)
                                    propValueSerializer.SerializeContents(serializationManager, propertyValue, writer, false);
                                else
                                    propValueSerializer.SerializeObject(serializationManager, propertyValue, writer);
                            }
                        }
                        else
                        {
                            serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, propertyValue.GetType().FullName)));
                        }
                    }
                }
 
                // serialize the contents
                try
                {
                    object contents = contentProperty.GetContents();
                    if (contents != null)
                    {
                        contents = GetMarkupExtensionFromValue(contents);
 
                        WorkflowMarkupSerializer propValueSerializer = serializationManager.GetSerializer(contents.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                        if (propValueSerializer == null)
                        {
                            serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, contents.GetType())));
                        }
                        else
                        {
                            //
 
 
 
                            //NOTE: THE FOLLOWING CONDITION ABOUT contentProperty.Property.PropertyType != typeof(object) is VALID AS WE SHOULD NOT SERIALIZE A PROPERTY OF TYPE OBJECT TO STRING
                            //IF WE DO THAT THEN WE DO NOT KNOWN WHAT WAS THE TYPE OF ORIGINAL OBJECT AND SERIALIZER WONT BE ABLE TO GET THE STRING BACK INTO THE CORRECT TYPE,
                            //AS THE TYPE INFORMATION IS LOST
                            if (propValueSerializer.CanSerializeToString(serializationManager, contents) &&
                                (contentProperty.Property == null || contentProperty.Property.PropertyType != typeof(object)))
                            {
                                string stringValue = propValueSerializer.SerializeToString(serializationManager, contents);
                                if (!string.IsNullOrEmpty(stringValue))
                                {
                                    stringValue = stringValue.Replace('\0', ' ');
                                    if (contents is MarkupExtension || !(stringValue.StartsWith("{", StringComparison.Ordinal) && stringValue.EndsWith("}", StringComparison.Ordinal)))
                                        writer.WriteString(stringValue);
                                    else
                                        writer.WriteString("{}" + stringValue);
                                }
                            }
                            else if (CollectionMarkupSerializer.IsValidCollectionType(contents.GetType()))
                            {
                                if (contentProperty.Property == null)
                                {
                                    IEnumerable enumerableContents = contents as IEnumerable;
                                    foreach (object childObj in enumerableContents)
                                    {
                                        if (childObj == null)
                                        {
                                            SerializeObject(serializationManager, new NullExtension(), writer);
                                        }
                                        else
                                        {
                                            object childObj2 = childObj;
                                            bool dictionaryEntry = (childObj2 is DictionaryEntry);
                                            try
                                            {
                                                if (dictionaryEntry)
                                                {
                                                    serializationManager.WorkflowMarkupStack.Push(childObj);
                                                    childObj2 = ((DictionaryEntry)childObj2).Value;
                                                }
                                                childObj2 = GetMarkupExtensionFromValue(childObj2);
                                                WorkflowMarkupSerializer childObjectSerializer = serializationManager.GetSerializer(childObj2.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                                                if (childObjectSerializer != null)
                                                    childObjectSerializer.SerializeObject(serializationManager, childObj2, writer);
                                                else
                                                    serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, childObj2.GetType())));
                                            }
                                            finally
                                            {
                                                if (dictionaryEntry)
                                                    serializationManager.WorkflowMarkupStack.Pop();
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    propValueSerializer.SerializeContents(serializationManager, contents, writer, false);
                                }
                            }
                            else
                            {
                                propValueSerializer.SerializeObject(serializationManager, contents, writer);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                    return;
                }
            }
 
            try
            {
                serializer.OnAfterSerialize(serializationManager, obj);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e));
                return;
            }
        }
        #endregion
 
        #region Overridable Methods
        protected virtual void OnBeforeSerialize(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
        }
 
        internal virtual void OnBeforeSerializeContents(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
 
        }
 
        protected virtual void OnAfterSerialize(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
        }
 
        protected virtual void OnBeforeDeserialize(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
        }
 
        internal virtual void OnBeforeDeserializeContents(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
 
        }
 
        protected virtual void OnAfterDeserialize(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
        }
 
        protected internal virtual bool ShouldSerializeValue(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
 
            if (value == null)
                return false;
 
            try
            {
                PropertyInfo property = serializationManager.Context.Current as PropertyInfo;
                if (property != null)
                {
                    Attribute[] attributes = Attribute.GetCustomAttributes(property, typeof(DefaultValueAttribute), true);
                    if (attributes.Length > 0)
                    {
                        DefaultValueAttribute defaultValueAttr = attributes[0] as DefaultValueAttribute;
                        if (defaultValueAttr.Value is IConvertible && value is IConvertible && object.Equals(Convert.ChangeType(defaultValueAttr.Value, property.PropertyType, CultureInfo.InvariantCulture), Convert.ChangeType(value, property.PropertyType, CultureInfo.InvariantCulture)))
                            return false;
                    }
                }
            }
            catch
            {
                //We purposely eat all the exceptions as Convert.ChangeType can throw but in that case
                //we continue with serialization
            }
 
            return true;
        }
 
        protected internal virtual bool CanSerializeToString(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (value == null)
                throw new ArgumentNullException("value");
 
            Type valueType = value.GetType();
            if (valueType.IsPrimitive || valueType == typeof(System.String) || valueType.IsEnum
                || typeof(Delegate).IsAssignableFrom(valueType) || typeof(IConvertible).IsAssignableFrom(valueType)
                || valueType == typeof(TimeSpan) || valueType == typeof(Guid) || valueType == typeof(DateTime))
                return true;
 
            return false;
        }
 
        protected internal virtual string SerializeToString(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (value == null)
                throw new ArgumentNullException("value");
 
            if (typeof(Delegate).IsAssignableFrom(value.GetType()))
                return ((Delegate)value).Method.Name;
            else if (typeof(DateTime).IsAssignableFrom(value.GetType()))
                return ((DateTime)value).ToString("o", CultureInfo.InvariantCulture);
            else
                return Convert.ToString(value, CultureInfo.InvariantCulture);
        }
 
        protected internal virtual object DeserializeFromString(WorkflowMarkupSerializationManager serializationManager, Type propertyType, string value)
        {
            return InternalDeserializeFromString(serializationManager, propertyType, value);
        }
 
        private object InternalDeserializeFromString(WorkflowMarkupSerializationManager serializationManager, Type propertyType, string value)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (propertyType == null)
                throw new ArgumentNullException("propertyType");
            if (value == null)
                throw new ArgumentNullException("value");
 
            object propVal = null;
            XmlReader reader = serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader;
            if (reader == null)
            {
                Debug.Assert(false, "XmlReader not available.");
                return null;
            }
            if (IsValidCompactAttributeFormat(value))
            {
                propVal = DeserializeFromCompactFormat(serializationManager, reader, value);
            }
            else
            {
                if (value.StartsWith("{}", StringComparison.Ordinal))
                    value = value.Substring(2);
                // Check for Nullable types
                if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    Type genericType = (Type)propertyType.GetGenericArguments()[0];
                    Debug.Assert(genericType != null);
                    propertyType = genericType;
                }
                if (propertyType.IsPrimitive || propertyType == typeof(System.String))
                {
                    propVal = Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture);
                }
                else if (propertyType.IsEnum)
                {
                    propVal = Enum.Parse(propertyType, value, true);
                }
                else if (typeof(Delegate).IsAssignableFrom(propertyType))
                {
                    // Just return the method name.  This must happen after Bind syntax has been checked.
                    propVal = value;
                }
                else if (typeof(TimeSpan) == propertyType)
                {
                    propVal = TimeSpan.Parse(value, CultureInfo.InvariantCulture);
                }
                else if (typeof(DateTime) == propertyType)
                {
                    propVal = DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
                }
                else if (typeof(Guid) == propertyType)
                {
                    propVal = Utility.CreateGuid(value);
                }
                else if (typeof(Type).IsAssignableFrom(propertyType))
                {
                    propVal = serializationManager.GetType(value);
                    if (propVal != null)
                    {
                        Type type = propVal as Type;
                        if (type.IsPrimitive || type.IsEnum || type == typeof(System.String))
                            return type;
                    }
                    ITypeProvider typeProvider = serializationManager.GetService(typeof(ITypeProvider)) as ITypeProvider;
                    if (typeProvider != null)
                    {
                        Type type = typeProvider.GetType(value);
                        if (type != null)
                            return type;
                    }
                    return value;
                }
                else if (typeof(IConvertible).IsAssignableFrom(propertyType))
                {
                    propVal = Convert.ChangeType(value, propertyType, CultureInfo.InvariantCulture);
                }
                else if (propertyType.IsAssignableFrom(value.GetType()))
                {
                    propVal = value;
                }
                else
                {
                    throw CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyNoLogic, new object[] { "", value.Trim(), "" }), reader);
                }
            }
            return propVal;
        }
 
        protected internal virtual IList GetChildren(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
 
            return null;
        }
 
        protected internal virtual void ClearChildren(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
        }
 
        protected internal virtual void AddChild(WorkflowMarkupSerializationManager serializationManager, object parentObject, object childObj)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (parentObject == null)
                throw new ArgumentNullException("parentObject");
            if (childObj == null)
                throw new ArgumentNullException("childObj");
 
            throw new Exception(SR.GetString(SR.Error_SerializerNoChildNotion, new object[] { parentObject.GetType().FullName }));
        }
 
        protected virtual object CreateInstance(WorkflowMarkupSerializationManager serializationManager, Type type)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (type == null)
                throw new ArgumentNullException("type");
 
            // Check the serializationTypeAuthorizer if there is one.
            ITypeAuthorizer serializationTypeAuthorizer = WorkflowMarkupSerializationHelpers.SerializationTypeAuthorizer;
            if (serializationTypeAuthorizer != null)
            {
                if (!serializationTypeAuthorizer.IsTypeAuthorized(type))
                {
                    throw new InvalidOperationException(SR.GetString(SR.Error_TypeNotAuthorized, type));
                }
            }
 
            ITypeAuthorizer localTypeAuthorizer = WorkflowMarkupSerializationHelpers.TypeAuthorizer;
            if (localTypeAuthorizer != null)
            {
                // The TypeAuthorizer should add the appropriate error to the errors collection.
                if (!localTypeAuthorizer.IsTypeAuthorized(type))
                {
                    return null;
                }
            }
            return Activator.CreateInstance(type);
        }
 
        protected internal virtual PropertyInfo[] GetProperties(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
 
            List<PropertyInfo> properties = new List<PropertyInfo>();
 
            object[] attributes = obj.GetType().GetCustomAttributes(typeof(RuntimeNamePropertyAttribute), true);
            string name = null;
            if (attributes.Length > 0)
                name = (attributes[0] as RuntimeNamePropertyAttribute).Name;
 
            foreach (PropertyInfo property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
            {
                DesignerSerializationVisibility visibility = Helpers.GetSerializationVisibility(property);
                if (visibility == DesignerSerializationVisibility.Hidden)
                    continue;
 
                if (visibility != DesignerSerializationVisibility.Content && (!property.CanWrite || property.GetSetMethod() == null))
                {
                    // work around for CodeObject which are ICollection needs to be serialized.
                    if (!(obj is CodeObject) || !typeof(ICollection).IsAssignableFrom(property.PropertyType))
                        continue;
                }
 
                TypeProvider typeProvider = serializationManager.GetService(typeof(ITypeProvider)) as TypeProvider;
 
                if (typeProvider != null)
                {
                    if (!typeProvider.IsSupportedProperty(property, obj))
                    {
                        continue;
                    }
                }
 
                if (name == null || !name.Equals(property.Name))
                    properties.Add(property);
                else
                    properties.Add(new ExtendedPropertyInfo(property, OnGetRuntimeNameValue, OnSetRuntimeNameValue, OnGetRuntimeQualifiedName));
            }
 
            return properties.ToArray();
        }
 
        protected internal virtual EventInfo[] GetEvents(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
 
            List<EventInfo> events = new List<EventInfo>();
            foreach (EventInfo evt in obj.GetType().GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
            {
                if (Helpers.GetSerializationVisibility(evt) == DesignerSerializationVisibility.Hidden)
                    continue;
 
                events.Add(evt);
            }
 
            return events.ToArray();
        }
 
        internal virtual ExtendedPropertyInfo[] GetExtendedProperties(WorkflowMarkupSerializationManager manager, object extendee)
        {
            return new ExtendedPropertyInfo[0];
        }
        private object OnGetRuntimeNameValue(ExtendedPropertyInfo extendedProperty, object extendee)
        {
            return extendedProperty.RealPropertyInfo.GetValue(extendee, null);
        }
 
        private void OnSetRuntimeNameValue(ExtendedPropertyInfo extendedProperty, object extendee, object value)
        {
            if (extendee != null && value != null)
                extendedProperty.RealPropertyInfo.SetValue(extendee, value, null);
        }
 
        private XmlQualifiedName OnGetRuntimeQualifiedName(ExtendedPropertyInfo extendedProperty, WorkflowMarkupSerializationManager manager, out string prefix)
        {
            prefix = StandardXomlKeys.Definitions_XmlNs_Prefix;
            return new XmlQualifiedName(extendedProperty.Name, StandardXomlKeys.Definitions_XmlNs);
        }
 
        #endregion
 
        #region Dependency Properties
        // 
 
        private IDictionary<DependencyProperty, object> GetDependencyProperties(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (serializationManager == null)
                throw new ArgumentNullException("serializationManager");
            if (obj == null)
                throw new ArgumentNullException("obj");
 
            List<PropertyInfo> pis = new List<PropertyInfo>();
            pis.AddRange(GetProperties(serializationManager, obj));
            List<EventInfo> eis = new List<EventInfo>();
            eis.AddRange(GetEvents(serializationManager, obj));
 
            Dictionary<DependencyProperty, object> dependencyProperties = new Dictionary<DependencyProperty, object>();
            DependencyObject dependencyObject = obj as DependencyObject;
            if (dependencyObject != null)
            {
                foreach (DependencyProperty dependencyProperty in dependencyObject.MetaDependencyProperties)
                {
                    Attribute[] visibilityAttrs = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
                    if (visibilityAttrs.Length > 0 && ((DesignerSerializationVisibilityAttribute)visibilityAttrs[0]).Visibility == DesignerSerializationVisibility.Hidden)
                        continue;
 
                    //If the dependency property is readonly and we have not marked it with DesignerSerializationVisibility.Content attribute the we should not
                    //serialize it
                    if ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly)
                    {
                        object[] serializationVisibilityAttribute = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
                        if (serializationVisibilityAttribute == null ||
                            serializationVisibilityAttribute.Length == 0 ||
                            ((DesignerSerializationVisibilityAttribute)serializationVisibilityAttribute[0]).Visibility != DesignerSerializationVisibility.Content)
                        {
                            continue;
                        }
                    }
 
                    object obj1 = null;
                    if (!dependencyProperty.IsAttached && !dependencyProperty.DefaultMetadata.IsMetaProperty)
                    {
                        if (dependencyProperty.IsEvent)
                            obj1 = LookupEvent(eis, dependencyProperty.Name);
                        else
                            obj1 = LookupProperty(pis, dependencyProperty.Name);
                        if (obj1 == null)
                        {
                            serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingCLRProperty, dependencyProperty.Name, obj.GetType().FullName)));
                            continue;
                        }
                    }
                    if (dependencyObject.IsBindingSet(dependencyProperty))
                    {
                        dependencyProperties.Add(dependencyProperty, dependencyObject.GetBinding(dependencyProperty));
                    }
                    else if (!dependencyProperty.IsEvent)
                    {
                        object propValue = null;
                        propValue = dependencyObject.GetValue(dependencyProperty);
                        if (!dependencyProperty.IsAttached && !dependencyProperty.DefaultMetadata.IsMetaProperty)
                        {
                            PropertyInfo propertyInfo = obj1 as PropertyInfo;
                            // if the propertyValue is assignable to the type in of the .net property then call the .net property's getter also
                            // else add the keep the value that we got 
                            if (propValue != null && propertyInfo.PropertyType.IsAssignableFrom(propValue.GetType()))
                                propValue = (obj1 as PropertyInfo).GetValue(dependencyObject, null);
                        }
                        dependencyProperties.Add(dependencyProperty, propValue);
                    }
                    else
                    {
                        dependencyProperties.Add(dependencyProperty, dependencyObject.GetHandler(dependencyProperty));
                    }
                }
                foreach (DependencyProperty dependencyProperty in dependencyObject.DependencyPropertyValues.Keys)
                {
                    Attribute[] visibilityAttrs = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
                    if (visibilityAttrs.Length > 0 && ((DesignerSerializationVisibilityAttribute)visibilityAttrs[0]).Visibility == DesignerSerializationVisibility.Hidden)
                        continue;
 
                    if (!dependencyProperty.DefaultMetadata.IsMetaProperty && dependencyProperty.IsAttached && VerifyAttachedPropertyConditions(dependencyProperty))
                        dependencyProperties.Add(dependencyProperty, dependencyObject.GetValue(dependencyProperty));
                }
            }
            return dependencyProperties;
        }
 
        private static bool VerifyAttachedPropertyConditions(DependencyProperty dependencyProperty)
        {
            if (dependencyProperty.IsEvent)
            {
                if (dependencyProperty.OwnerType.GetField(dependencyProperty.Name + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) == null)
                    return false;
                MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Add" + dependencyProperty.Name + "Handler", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
                if (methodInfo == null)
                    return false;
                ParameterInfo[] parameters = methodInfo.GetParameters();
                if (parameters != null && parameters.Length == 2 && parameters[0].ParameterType == typeof(object) && parameters[1].ParameterType == typeof(object))
                    return true;
            }
            else
            {
                if (dependencyProperty.OwnerType.GetField(dependencyProperty.Name + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) == null)
                    return false;
                MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Set" + dependencyProperty.Name, BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
                if (methodInfo == null)
                    return false;
                ParameterInfo[] parameters = methodInfo.GetParameters();
                if (parameters != null && parameters.Length == 2 && parameters[0].ParameterType == typeof(object) && parameters[1].ParameterType == typeof(object))
                    return true;
            }
            return false;
        }
 
        private void SetDependencyPropertyValue(WorkflowMarkupSerializationManager serializationManager, object obj, DependencyProperty dependencyProperty, object value)
        {
            if (dependencyProperty == null)
                throw new ArgumentNullException("dependencyProperty");
            if (obj == null)
                throw new ArgumentNullException("obj");
 
            DependencyObject dependencyObject = obj as DependencyObject;
            if (dependencyObject == null)
                throw new ArgumentException(SR.GetString(SR.Error_InvalidArgumentValue), "obj");
 
            if (dependencyProperty.IsEvent)
            {
                if (value is ActivityBind)
                    dependencyObject.SetBinding(dependencyProperty, value as ActivityBind);
                else if (dependencyProperty.IsAttached)
                {
                    MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Add" + dependencyProperty.Name + "Handler", BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
                    if (methodInfo != null)
                    {
                        ParameterInfo[] parameters = methodInfo.GetParameters();
                        if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(object) || parameters[1].ParameterType != typeof(object))
                            methodInfo = null;
                    }
                    if (methodInfo != null)
                        WorkflowMarkupSerializationHelpers.SetEventHandlerName(dependencyObject, dependencyProperty.Name, value as string);
                    else
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingAddHandler, dependencyProperty.Name, dependencyProperty.OwnerType.FullName)));
                }
                else
                    WorkflowMarkupSerializationHelpers.SetEventHandlerName(dependencyObject, dependencyProperty.Name, value as string);
            }
            else
            {
                if (value is ActivityBind)
                    dependencyObject.SetBinding(dependencyProperty, value as ActivityBind);
                else if (value is string && TypeProvider.IsAssignable(typeof(Type), dependencyProperty.PropertyType))
                    Helpers.SetDesignTimeTypeName(obj, dependencyProperty, value as string);
                else if (dependencyProperty.IsAttached)
                {
                    MethodInfo methodInfo = dependencyProperty.OwnerType.GetMethod("Set" + dependencyProperty.Name, BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
                    if (methodInfo != null)
                    {
                        ParameterInfo[] parameters = methodInfo.GetParameters();
                        if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(object) || parameters[1].ParameterType != typeof(object))
                            methodInfo = null;
                    }
                    if (methodInfo != null)
                        methodInfo.Invoke(null, new object[] { dependencyObject, value });
                    else
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_MissingSetAccessor, dependencyProperty.Name, dependencyProperty.OwnerType.FullName)));
                }
                else
                {
                    List<PropertyInfo> pis = new List<PropertyInfo>();
                    pis.AddRange(GetProperties(serializationManager, obj));
                    //The following condition is workaround for the partner team as they depend on the dependencyObject.SetValue being called
                    //for non assignable property values
                    PropertyInfo pi = LookupProperty(pis, dependencyProperty.Name);
                    if (pi != null &&
                        (value == null || pi.PropertyType.IsAssignableFrom(value.GetType())))
                    {
                        if (pi.CanWrite)
                        {
                            pi.SetValue(obj, value, null);
                        }
                        else if (typeof(ICollection<string>).IsAssignableFrom(value.GetType()))
                        {
                            ICollection<string> propVal = pi.GetValue(obj, null) as ICollection<string>;
                            ICollection<string> deserializedValue = value as ICollection<string>;
                            if (propVal != null && deserializedValue != null)
                            {
                                foreach (string content in deserializedValue)
                                    propVal.Add(content);
                            }
                        }
                    }
                    else
                    {
                        dependencyObject.SetValue(dependencyProperty, value);
                    }
                }
            }
        }
        #endregion
 
        #region Private Helpers
 
        #region Reader/Writer
        private void AdvanceReader(XmlReader reader)
        {
            //Compressed what process mapping pi used to do
            while (reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.Text && reader.Read());
        }
        #endregion
 
        #region Exception Handling
        internal static WorkflowMarkupSerializationException CreateSerializationError(Exception e, XmlReader reader)
        {
            return CreateSerializationError(null, e, reader);
        }
        internal static WorkflowMarkupSerializationException CreateSerializationError(string message, XmlReader reader)
        {
            return CreateSerializationError(message, null, reader);
        }
        internal static WorkflowMarkupSerializationException CreateSerializationError(string message, Exception e, XmlReader reader)
        {
            string errorMsg = message;
            if (string.IsNullOrEmpty(errorMsg))
                errorMsg = e.Message;
 
            IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo;
            if (xmlLineInfo != null)
                return new WorkflowMarkupSerializationException(errorMsg, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);
            else
                return new WorkflowMarkupSerializationException(errorMsg, 0, 0);
        }
        #endregion
 
        #region Type Creation Support
        private static string GetClrFullName(WorkflowMarkupSerializationManager serializationManager, XmlQualifiedName xmlQualifiedName)
        {
            string xmlns = xmlQualifiedName.Namespace;
            string typeName = xmlQualifiedName.Name;
 
            List<WorkflowMarkupSerializerMapping> xmlnsMappings = null;
            if (!serializationManager.XmlNamespaceBasedMappings.TryGetValue(xmlns, out xmlnsMappings) || xmlnsMappings.Count == 0)
                return xmlQualifiedName.Namespace + "." + xmlQualifiedName.Name;
 
            WorkflowMarkupSerializerMapping xmlnsMapping = xmlnsMappings[0];
 
            string assemblyName = xmlnsMapping.AssemblyName;
            string dotNetnamespaceName = xmlnsMapping.ClrNamespace;
 
            // append dot net namespace name
            string fullTypeName = xmlQualifiedName.Name;
            if (dotNetnamespaceName.Length > 0)
                fullTypeName = (dotNetnamespaceName + "." + xmlQualifiedName.Name);
 
            return fullTypeName;
        }
 
        private object CreateInstance(WorkflowMarkupSerializationManager serializationManager, XmlQualifiedName xmlQualifiedName, XmlReader reader)
        {
            object obj = null;
            // resolve the type
            Type type = null;
            try
            {
                type = serializationManager.GetType(xmlQualifiedName);
            }
            catch (Exception e)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolvedWithInnerError, new object[] { GetClrFullName(serializationManager, xmlQualifiedName), e.Message }), e, reader));
                return null;
            }
            if (type == null && !xmlQualifiedName.Name.EndsWith("Extension", StringComparison.Ordinal))
            {
                string typename = xmlQualifiedName.Name + "Extension";
                try
                {
                    type = serializationManager.GetType(new XmlQualifiedName(typename, xmlQualifiedName.Namespace));
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolvedWithInnerError, new object[] { GetClrFullName(serializationManager, xmlQualifiedName), e.Message }), e, reader));
                    return null;
                }
            }
 
            if (type == null)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerTypeNotResolved, new object[] { GetClrFullName(serializationManager, xmlQualifiedName) }), reader));
                return null;
            }
 
            if (type.IsPrimitive || type == typeof(string) || type == typeof(decimal) || type == typeof(DateTime) ||
                type == typeof(TimeSpan) || type.IsEnum || type == typeof(Guid))
            {
                try
                {
                    string stringValue = reader.ReadString();
                    if (type == typeof(DateTime))
                    {
                        obj = DateTime.Parse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
                    }
                    else if (type.IsPrimitive || type == typeof(decimal) || type == typeof(TimeSpan) || type.IsEnum || type == typeof(Guid))
                    {
                        //These non CLS-compliant are not supported in the XmlReader 
                        TypeConverter typeConverter = TypeDescriptor.GetConverter(type);
                        if (typeConverter != null && typeConverter.CanConvertFrom(typeof(string)))
                            obj = typeConverter.ConvertFrom(null, CultureInfo.InvariantCulture, stringValue);
                        else if (typeof(IConvertible).IsAssignableFrom(type))
                            obj = Convert.ChangeType(stringValue, type, CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        obj = stringValue;
                    }
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, e.Message), reader));
                    return null;
                }
            }
            else
            {
                // get the serializer
                WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(type, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                if (serializer == null)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, type.FullName), reader));
                    return null;
                }
 
                // create an instance
                try
                {
                    obj = serializer.CreateInstance(serializationManager, type);
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, type.FullName, e.Message), reader));
                    return null;
                }
            }
            return obj;
        }
        #endregion
 
        #region Simple and Complex property Serialization Support
        private void DeserializeCompoundProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj)
        {
            string propertyName = reader.LocalName;
            bool isReadOnly = false;
 
            DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty;
            PropertyInfo property = serializationManager.Context.Current as PropertyInfo;
            if (dependencyProperty != null)
                isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly);
            else if (property != null)
                isReadOnly = !property.CanWrite;
            else
            {
                Debug.Assert(false);
                return;
            }
 
            //Deserialize compound properties
            if (isReadOnly)
            {
                object propValue = null;
                if (dependencyProperty != null && obj is DependencyObject)
                {
                    if (((DependencyObject)obj).IsBindingSet(dependencyProperty))
                        propValue = ((DependencyObject)obj).GetBinding(dependencyProperty);
                    else if (!dependencyProperty.IsEvent)
                        propValue = ((DependencyObject)obj).GetValue(dependencyProperty);
                    else
                        propValue = ((DependencyObject)obj).GetHandler(dependencyProperty);
                }
                else if (property != null)
                    propValue = property.CanRead ? property.GetValue(obj, null) : null;
 
                if (propValue != null)
                    DeserializeContents(serializationManager, propValue, reader);
                else
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerReadOnlyPropertyAndValueIsNull, propertyName, obj.GetType().FullName), reader));
            }
            else if (!reader.IsEmptyElement)
            {
                //
                if (reader.HasAttributes)
                {
                    //We allow xmlns on the complex property nodes
                    while (reader.MoveToNextAttribute())
                    {
                        // 
                        if (string.Equals(reader.LocalName, "xmlns", StringComparison.Ordinal) || string.Equals(reader.Prefix, "xmlns", StringComparison.Ordinal))
                            continue;
                        else
                            serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerAttributesFoundInComplexProperty, propertyName, obj.GetType().FullName), reader));
                    }
                }
 
                do
                {
                    if (!reader.Read())
                        return;
                } while (reader.NodeType != XmlNodeType.Text && reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.ProcessingInstruction && reader.NodeType != XmlNodeType.EndElement);
 
                if (reader.NodeType == XmlNodeType.Text)
                {
                    this.DeserializeSimpleProperty(serializationManager, reader, obj, reader.Value);
                }
                else
                {
                    AdvanceReader(reader);
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        object propValue = DeserializeObject(serializationManager, reader);
                        if (propValue != null)
                        {
                            propValue = GetValueFromMarkupExtension(serializationManager, propValue);
 
                            if (propValue != null && propValue.GetType() == typeof(string) && ((string)propValue).StartsWith("{}", StringComparison.Ordinal))
                                propValue = ((string)propValue).Substring(2);
 
                            if (dependencyProperty != null)
                            {
                                //Get the serializer for the property type
                                WorkflowMarkupSerializer objSerializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                                if (objSerializer == null)
                                {
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader));
                                    return;
                                }
 
                                try
                                {
                                    objSerializer.SetDependencyPropertyValue(serializationManager, obj, dependencyProperty, propValue);
                                }
                                catch (Exception e)
                                {
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e, reader));
                                    return;
                                }
                            }
                            else if (property != null)
                            {
                                try
                                {
                                    property.SetValue(obj, propValue, null);
                                }
                                catch
                                {
                                    serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerComplexPropertySetFailed, new object[] { propertyName, propertyName, obj.GetType().Name })));
                                }
                            }
                        }
                    }
                }
            }
        }
 
        private void DeserializeSimpleProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj, string value)
        {
            Type propertyType = null;
            bool isReadOnly = false;
 
            DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty;
            PropertyInfo property = serializationManager.Context.Current as PropertyInfo;
            if (dependencyProperty != null)
            {
                propertyType = dependencyProperty.PropertyType;
                isReadOnly = ((dependencyProperty.DefaultMetadata.Options & DependencyPropertyOptions.ReadOnly) == DependencyPropertyOptions.ReadOnly);
            }
            else if (property != null)
            {
                propertyType = property.PropertyType;
                isReadOnly = !property.CanWrite;
            }
            else
            {
                Debug.Assert(false);
                return;
            }
 
            if (isReadOnly && !typeof(ICollection<string>).IsAssignableFrom(propertyType))
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyReadOnly, new object[] { property.Name, property.Name, obj.GetType().FullName }), reader));
                return;
            }
 
            DeserializeSimpleMember(serializationManager, propertyType, reader, obj, value);
        }
 
        private void DeserializeEvent(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object obj, string value)
        {
            Type eventType = null;
 
            EventInfo evt = serializationManager.Context.Current as EventInfo;
            DependencyProperty dependencyEvent = serializationManager.Context.Current as DependencyProperty;
            if (dependencyEvent != null)
                eventType = dependencyEvent.PropertyType;
            else if (evt != null)
                eventType = evt.EventHandlerType;
            else
            {
                Debug.Assert(false);
                return;
            }
 
            DeserializeSimpleMember(serializationManager, eventType, reader, obj, value);
        }
 
        private void DeserializeSimpleMember(WorkflowMarkupSerializationManager serializationManager, Type memberType, XmlReader reader, object obj, string value)
        {
            //Get the serializer for the member type
            WorkflowMarkupSerializer memberSerializer = serializationManager.GetSerializer(memberType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
            if (memberSerializer == null)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, memberType.FullName), reader));
                return;
            }
 
            //Try to deserialize
            object memberValue = null;
            try
            {
                memberValue = memberSerializer.DeserializeFromString(serializationManager, memberType, value);
                memberValue = GetValueFromMarkupExtension(serializationManager, memberValue);
 
                DependencyProperty dependencyProperty = serializationManager.Context.Current as DependencyProperty;
                if (dependencyProperty != null)
                {
                    //Get the serializer for the property type
                    WorkflowMarkupSerializer objSerializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                    if (objSerializer == null)
                    {
                        serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader));
                        return;
                    }
 
                    objSerializer.SetDependencyPropertyValue(serializationManager, obj, dependencyProperty, memberValue);
                }
                else
                {
                    EventInfo evt = serializationManager.Context.Current as EventInfo;
                    if (evt != null)
                    {
                        try
                        {
                            WorkflowMarkupSerializationHelpers.SetEventHandlerName(obj, evt.Name, memberValue as string);
                        }
                        catch (Exception e)
                        {
                            while (e is TargetInvocationException && e.InnerException != null)
                                e = e.InnerException;
                            serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader));
                        }
                    }
                    else
                    {
                        PropertyInfo property = serializationManager.Context.Current as PropertyInfo;
                        if (property != null)
                        {
                            try
                            {
                                if (memberValue is string && TypeProvider.IsAssignable(typeof(Type), property.PropertyType))
                                {
                                    string key = property.ReflectedType.FullName + "." + property.Name;
                                    Helpers.SetDesignTimeTypeName(obj, key, memberValue as string);
                                }
                                else if (property.CanWrite)
                                {
                                    property.SetValue(obj, memberValue, null);
                                }
                                else if (typeof(ICollection<string>).IsAssignableFrom(memberValue.GetType()))
                                {
                                    ICollection<string> propVal = property.GetValue(obj, null) as ICollection<string>;
                                    ICollection<string> deserializedValue = memberValue as ICollection<string>;
                                    if (propVal != null && deserializedValue != null)
                                    {
                                        foreach (string content in deserializedValue)
                                            propVal.Add(content);
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                while (e is TargetInvocationException && e.InnerException != null)
                                    e = e.InnerException;
                                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader));
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                while (e is TargetInvocationException && e.InnerException != null)
                    e = e.InnerException;
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerMemberSetFailed, new object[] { reader.LocalName, reader.Value, reader.LocalName, obj.GetType().FullName, e.Message }), e, reader));
            }
        }
        #endregion
 
        #region DependencyProperty Support
 
        [SuppressMessage("Microsoft.Globalization", "CA1307:SpecifyStringComparison", MessageId = "System.String.IndexOf(System.String)", Justification = "string comparisons are just used to lookup method/property names from compiled system.type which should not cause any issue irrespective of comparisons mode used")]
        private DependencyProperty ResolveDependencyProperty(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, object attachedObj, string fullPropertyName)
        {
            Type ownerType = null;
            string propertyName = String.Empty;
            int separatorIndex = fullPropertyName.IndexOf(".");
            if (separatorIndex != -1)
            {
                string ownerTypeName = fullPropertyName.Substring(0, separatorIndex);
                propertyName = fullPropertyName.Substring(separatorIndex + 1);
                if (!String.IsNullOrEmpty(ownerTypeName) && !String.IsNullOrEmpty(propertyName))
                    ownerType = serializationManager.GetType(new XmlQualifiedName(ownerTypeName, reader.LookupNamespace(reader.Prefix)));
            }
            else
            {
                ownerType = attachedObj.GetType();
                propertyName = fullPropertyName;
            }
 
            if (ownerType == null)
                return null;
 
            //We need to make sure that the register method is always called for the dynamic property before we try to resolve it
            //In cases of attached properties if this statement is not there then the dynamic property wont be found as it is
            //not registered till the first access of the static field
            DependencyProperty dependencyProperty = null;
 
            FieldInfo fieldInfo = ownerType.GetField(propertyName + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
            if (fieldInfo == null)
                fieldInfo = ownerType.GetField(propertyName + "Event", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
            if (fieldInfo != null)
            {
                dependencyProperty = fieldInfo.GetValue(attachedObj) as DependencyProperty;
                if (dependencyProperty != null)
                {
                    object[] attributes = dependencyProperty.DefaultMetadata.GetAttributes(typeof(DesignerSerializationVisibilityAttribute));
                    if (attributes.Length > 0)
                    {
                        DesignerSerializationVisibilityAttribute serializationVisibilityAttribute = attributes[0] as DesignerSerializationVisibilityAttribute;
                        if (serializationVisibilityAttribute.Visibility == DesignerSerializationVisibility.Hidden)
                            dependencyProperty = null;
                    }
                }
            }
 
            return dependencyProperty;
        }
        #endregion
 
        #region GetAuthorizedTypes
        static void AddUnauthorizedTypes(IList<AuthorizedType> authorizedTypes)
        {
            AuthorizedType authType = new AuthorizedType();
            authType.Assembly = "System.Activities.Presentation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Activities.Presentation";
            authType.TypeName = "WorkflowDesigner";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Activities.Presentation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Activities.Presentation.Internal.PropertyEditing";
            authType.TypeName = "PropertyInspectorFontAndColorDictionary";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Windows.Data";
            authType.TypeName = "ObjectDataProvider";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Windows.Data";
            authType.TypeName = "ObjectDataProvider";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Windows";
            authType.TypeName = "ResourceDictionary";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Windows";
            authType.TypeName = "ResourceDictionary";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
            authType.Namespace = "System.Configuration.Install";
            authType.TypeName = "AssemblyInstaller";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType.Assembly = "System.Configuration.Install, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
            authType.Namespace = "System.Configuration.Install";
            authType.TypeName = "AssemblyInstaller";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType.Assembly = "System.Configuration.Install, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
            authType.Namespace = "System.Configuration.Install";
            authType.TypeName = "AssemblyInstaller";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.Windows.Forms";
            authType.TypeName = "BindingSource";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.Windows.Forms";
            authType.TypeName = "BindingSource";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.ComponentModel.Composition.Hosting";
            authType.TypeName = "DirectoryCatalog";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.ComponentModel.Composition, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.ComponentModel.Composition.Hosting";
            authType.TypeName = "AssemblyCatalog";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            // The default constructor of System.Workflow.ComponentModel.Design.WorkflowView displays a set of dialog box on a
            // non-windowed application. Like if you are running the WorkflowCompiler in a console application.
            authType = new AuthorizedType();
            authType.Assembly = "System.Workflow.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Workflow.ComponentModel.Design";
            authType.TypeName = "WorkflowView";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Workflow.ComponentModel.Design";
            authType.TypeName = "WorkflowView";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            // The default constructor of System.Speech.Recognition.SpeechRecognizer displays a dialog box on a
            // non-windowed application. Like if you are running the WorkflowCompiler in a console application.
            authType = new AuthorizedType();
            authType.Assembly = "System.Speech, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Speech.Recognition";
            authType.TypeName = "SpeechRecognizer";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.Speech, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
            authType.Namespace = "System.Speech.Recognition";
            authType.TypeName = "SpeechRecognizer";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            // The default constructor of System.ServiceModel.ComIntegration.ServiceMoniker throws a remoting
            // exception that can cause the calling process to fail, leading to denial of service.
            authType = new AuthorizedType();
            authType.Assembly = "System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.ServiceModel.ComIntegration";
            authType.TypeName = "ServiceMoniker";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            authType = new AuthorizedType();
            authType.Assembly = "System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.ServiceModel.ComIntegration";
            authType.TypeName = "ServiceMoniker";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
 
            // The default constructor of System.ServiceModel.ServiceMoniker40.ServiceMoniker40 throws a remoting
            // exception that can cause the calling process to fail, leading to denial of service.
            authType = new AuthorizedType();
            authType.Assembly = "System.ServiceModel.ServiceMoniker40, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
            authType.Namespace = "System.ServiceModel.ServiceMoniker40";
            authType.TypeName = "ServiceMoniker40";
            authType.Authorized = "false";
            authorizedTypes.Add(authType);
        }
 
        static void GetAuthorizedTypes()
        {
            if (WorkflowMarkupSerializer.StaticAuthorizedTypes == null)
            {
                lock (WorkflowMarkupSerializer.StaticAuthTypesLockObject)
                {
                    if (WorkflowMarkupSerializer.StaticAuthorizedTypes == null)
                    {
                        try
                        {
                            IList<AuthorizedType> authorizedTypes;
 
                            IDictionary<string, IList<AuthorizedType>> authorizedTypesDictionary =
                                ConfigurationManager.GetSection("System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes") as IDictionary<string, IList<AuthorizedType>>;
                            // The WorkflowMarkupSerializer will only look for AuthorizedType entries under the 4.0 section.
                            Version targetVersion = new Version("4.0");
 
                            string normalizedVersionString = string.Format(CultureInfo.InvariantCulture, "v{0}.{1}", targetVersion.Major, targetVersion.Minor);
 
                            // If there was nothing in config, we still need to create an "authorizedTypes" collection with the hard coded UNauthorized types.
                            if ((authorizedTypesDictionary == null) || !authorizedTypesDictionary.TryGetValue(normalizedVersionString, out authorizedTypes))
                            {
                                authorizedTypes = new List<AuthorizedType>();
                            }
 
                            // Now add the types that we don't ever want to be authorized.
                            if (!AppSettings.DisableXOMLSerializerDefaultUnauthorizedTypes)
                            {
                                AddUnauthorizedTypes(authorizedTypes);
                            }
 
                            WorkflowMarkupSerializer.StaticAuthorizedTypes = new ReadOnlyCollection<AuthorizedType>(authorizedTypes);
                        }
                        catch
                        {
                        }
                    }
                }
            }
        }
        #endregion
 
        #region SerializerTypeAuthorizerClass
        private sealed class SerializerTypeAuthorizerClass : ITypeAuthorizer
        {
            private IList<AuthorizedType> authorizedTypes;
            public SerializerTypeAuthorizerClass(IList<AuthorizedType> authorizedTypes)
            {
                this.authorizedTypes = authorizedTypes;
            }
 
            public bool IsTypeAuthorized(Type typeToAuthorize)
            {
                if (typeToAuthorize == null)
                {
                    throw new ArgumentNullException("typeToAuthorize");
                }
 
                // For deserialization, assume all types are authorized unless the are SPECIFICALLY
                // not authorized.
                bool authorized = true;
                if (this.authorizedTypes != null)
                {
                    foreach (AuthorizedType authorizedType in this.authorizedTypes)
                    {
                        if (authorizedType.RegularExpression.IsMatch(typeToAuthorize.AssemblyQualifiedName))
                        {
                            authorized = (String.Compare(bool.TrueString, authorizedType.Authorized, StringComparison.OrdinalIgnoreCase) == 0);
                            if (!authorized)
                                break;
                        }
                    }
                }
                return authorized;
            }
        }
        #endregion
 
        #region SafeXmlNodeWriter
        private sealed class SafeXmlNodeWriter : IDisposable
        {
            private XmlNodeType xmlNodeType = XmlNodeType.None;
            private WorkflowMarkupSerializationManager serializationManager = null;
 
            public SafeXmlNodeWriter(WorkflowMarkupSerializationManager serializationManager, object owner, object property, XmlNodeType xmlNodeType)
            {
                this.serializationManager = serializationManager;
                this.xmlNodeType = xmlNodeType;
 
                XmlWriter writer = serializationManager.WorkflowMarkupStack[typeof(XmlWriter)] as XmlWriter;
                if (writer == null)
                    throw new InvalidOperationException(SR.GetString(SR.Error_InternalSerializerError));
 
                string prefix = String.Empty, tagName = String.Empty, xmlns = String.Empty;
 
                DependencyProperty dependencyProperty = property as DependencyProperty;
                if (dependencyProperty != null)
                {
                    if (!dependencyProperty.IsAttached && xmlNodeType == XmlNodeType.Attribute)
                    {
                        tagName = dependencyProperty.Name;
                        xmlns = String.Empty;
                    }
                    else
                    {
                        XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(dependencyProperty.OwnerType, out prefix);
                        tagName = qualifiedName.Name + "." + dependencyProperty.Name;
                        xmlns = qualifiedName.Namespace;
                    }
                }
                else if (property is MemberInfo)
                {
                    ExtendedPropertyInfo extendedProperty = property as ExtendedPropertyInfo;
                    if (extendedProperty != null)
                    {
                        XmlQualifiedName qualifiedName = extendedProperty.GetXmlQualifiedName(this.serializationManager, out prefix);
                        tagName = qualifiedName.Name;
                        xmlns = qualifiedName.Namespace;
                    }
                    else if (this.xmlNodeType == XmlNodeType.Element)
                    {
                        XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(owner.GetType(), out prefix);
                        tagName = qualifiedName.Name + "." + ((MemberInfo)property).Name;
                        xmlns = qualifiedName.Namespace;
                    }
                    else
                    {
                        tagName = ((MemberInfo)property).Name;
                        xmlns = String.Empty;
                    }
                }
                else
                {
                    XmlQualifiedName qualifiedName = this.serializationManager.GetXmlQualifiedName(owner.GetType(), out prefix);
                    tagName = qualifiedName.Name;
                    xmlns = qualifiedName.Namespace;
                }
 
                //verify the node name is valid. This may happen for design time names as 
                // "(Parameter) PropName"
                tagName = XmlConvert.EncodeName(tagName);
 
                if (this.xmlNodeType == XmlNodeType.Element)
                {
                    writer.WriteStartElement(prefix, tagName, xmlns);
                    this.serializationManager.WriterDepth += 1;
                }
                else if (this.xmlNodeType == XmlNodeType.Attribute)
                {
                    writer.WriteStartAttribute(prefix, tagName, xmlns);
                }
            }
 
            #region IDisposable Members
            void IDisposable.Dispose()
            {
                XmlWriter writer = this.serializationManager.WorkflowMarkupStack[typeof(XmlWriter)] as XmlWriter;
                if (writer != null && writer.WriteState != WriteState.Error)
                {
                    if (this.xmlNodeType == XmlNodeType.Element)
                    {
                        writer.WriteEndElement();
                        this.serializationManager.WriterDepth -= 1;
                    }
                    else if (writer.WriteState == WriteState.Attribute)
                    {
                        writer.WriteEndAttribute();
                    }
                }
            }
            #endregion
        }
        #endregion
 
        #region Property Info Lookup
        private static PropertyInfo LookupProperty(IList<PropertyInfo> properties, string propertyName)
        {
            if (properties != null && !string.IsNullOrEmpty(propertyName))
            {
                foreach (PropertyInfo property in properties)
                {
                    if (property.Name == propertyName)
                        return property;
                }
            }
            return null;
        }
 
        private static EventInfo LookupEvent(IList<EventInfo> events, string eventName)
        {
            if (events != null && !string.IsNullOrEmpty(eventName))
            {
                foreach (EventInfo evt in events)
                {
                    if (evt.Name == eventName)
                        return evt;
                }
            }
            return null;
        }
        #endregion
 
        #endregion
 
        #region Compact Attribute Support
 
        internal bool IsValidCompactAttributeFormat(string attributeValue)
        {
            return (attributeValue.Length > 0 && attributeValue.StartsWith("{", StringComparison.Ordinal) && !attributeValue.StartsWith("{}", StringComparison.Ordinal) && attributeValue.EndsWith("}", StringComparison.Ordinal));
        }
 
        // This function parses the data bind syntax (markup extension in xaml terms).  The syntax is:
        // {ObjectTypeName arg1, arg2, name3=arg3, name4=arg4, ...}
        // For example, an ActivityBind would have the syntax as the following:
        // {wcm:ActivityBind ID=Workflow1, Path=error1}
        // We also support positional arguments, so the above expression is equivalent to 
        // {wcm:ActivityBind Workflow1, Path=error1} or {wcm:ActivityBind Workflow1, error1}
        // Notice that the object must have the appropriate constructor to support positional arugments.
        // There should be no constructors that takes the same number of arugments, regardless of their types.
        internal object DeserializeFromCompactFormat(WorkflowMarkupSerializationManager serializationManager, XmlReader reader, string attrValue)
        {
            if (attrValue.Length == 0 || !attrValue.StartsWith("{", StringComparison.Ordinal) || !attrValue.EndsWith("}", StringComparison.Ordinal))
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.IncorrectSyntax, attrValue), reader));
                return null;
            }
 
            // check for correct format:  typename name=value name=value
            int argIndex = attrValue.IndexOf(" ", StringComparison.Ordinal);
            if (argIndex == -1)
                argIndex = attrValue.IndexOf("}", StringComparison.Ordinal);
 
            string typename = attrValue.Substring(1, argIndex - 1).Trim();
            string arguments = attrValue.Substring(argIndex + 1, attrValue.Length - (argIndex + 1));
            // lookup the type of the target
            string prefix = String.Empty;
            int typeIndex = typename.IndexOf(":", StringComparison.Ordinal);
            if (typeIndex >= 0)
            {
                prefix = typename.Substring(0, typeIndex);
                typename = typename.Substring(typeIndex + 1);
            }
 
            Type type = serializationManager.GetType(new XmlQualifiedName(typename, reader.LookupNamespace(prefix)));
            if (type == null && !typename.EndsWith("Extension", StringComparison.Ordinal))
            {
                typename = typename + "Extension";
                type = serializationManager.GetType(new XmlQualifiedName(typename, reader.LookupNamespace(prefix)));
            }
            if (type == null)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_MarkupSerializerTypeNotResolved, typename), reader));
                return null;
            }
 
            // Check the serializationTypeAuthorizer if there is one.
            ITypeAuthorizer serializationTypeAuthorizer = WorkflowMarkupSerializationHelpers.SerializationTypeAuthorizer;
            if (serializationTypeAuthorizer != null)
            {
                if (!serializationTypeAuthorizer.IsTypeAuthorized(type))
                {
                    throw new InvalidOperationException(SR.GetString(SR.Error_TypeNotAuthorized, type));
                }
            }
 
            ITypeAuthorizer localTypeAuthorizer = WorkflowMarkupSerializationHelpers.TypeAuthorizer;
            if (localTypeAuthorizer != null)
            {
                // The TypeAuthorizer should add the appropriate error to the errors collection.
                if (!localTypeAuthorizer.IsTypeAuthorized(type))
                {
                    return null;
                }
            }
 
            // Break apart the argument string.
            object obj = null;
            Dictionary<string, object> namedArgs = new Dictionary<string, object>();
            ArrayList argTokens = null;
            try
            {
                argTokens = TokenizeAttributes(serializationManager, arguments, (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LineNumber : 1, (reader is IXmlLineInfo) ? ((IXmlLineInfo)reader).LinePosition : 1);
            }
            catch (Exception error)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_MarkupExtensionDeserializeFailed, attrValue, error.Message), reader));
                return null;
            }
            if (argTokens != null)
            {
                // Process the positional arugments and find the correct constructor to call.
                ArrayList positionalArgs = new ArrayList();
                bool firstEqual = true;
                for (int i = 0; i < argTokens.Count; i++)
                {
                    char token = (argTokens[i] is char) ? (char)argTokens[i] : '\0';
                    if (token == '=')
                    {
                        if (positionalArgs.Count > 0 && firstEqual)
                            positionalArgs.RemoveAt(positionalArgs.Count - 1);
                        firstEqual = false;
                        namedArgs.Add(argTokens[i - 1] as string, argTokens[i + 1] as string);
                        i++;
                    }
                    if (token == ',')
                        continue;
 
                    if (namedArgs.Count == 0)
                        positionalArgs.Add(argTokens[i] as string);
                }
 
                if (positionalArgs.Count > 0)
                {
                    ConstructorInfo matchConstructor = null;
                    ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                    ParameterInfo[] matchParameters = null;
                    foreach (ConstructorInfo ctor in constructors)
                    {
                        ParameterInfo[] parameters = ctor.GetParameters();
                        if (parameters.Length == positionalArgs.Count)
                        {
                            matchConstructor = ctor;
                            matchParameters = parameters;
                            break;
                        }
                    }
 
                    if (matchConstructor != null)
                    {
                        for (int i = 0; i < positionalArgs.Count; i++)
                        {
                            positionalArgs[i] = XmlConvert.DecodeName((string)positionalArgs[i]);
                            string argVal = (string)positionalArgs[i];
                            RemoveEscapes(ref argVal);
                            positionalArgs[i] = InternalDeserializeFromString(serializationManager, matchParameters[i].ParameterType, argVal);
                            positionalArgs[i] = GetValueFromMarkupExtension(serializationManager, positionalArgs[i]);
                        }
 
                        obj = Activator.CreateInstance(type, positionalArgs.ToArray());
                    }
                }
                else
                    obj = Activator.CreateInstance(type);
            }
            else
                obj = Activator.CreateInstance(type);
 
            if (obj == null)
            {
                serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_CantCreateInstanceOfBaseType, type.FullName), reader));
                return null;
            }
 
            if (namedArgs.Count > 0)
            {
                WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(obj.GetType(), typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                if (serializer == null)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, obj.GetType().FullName), reader));
                    return obj;
                }
                List<PropertyInfo> properties = new List<PropertyInfo>();
                try
                {
                    properties.AddRange(serializer.GetProperties(serializationManager, obj));
                    properties.AddRange(serializationManager.GetExtendedProperties(obj));
                }
                catch (Exception e)
                {
                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerThrewException, obj.GetType().FullName, e.Message), e, reader));
                    return obj;
                }
 
                foreach (string key in namedArgs.Keys)
                {
                    string argName = key;
                    string argVal = namedArgs[key] as string;
                    RemoveEscapes(ref argName);
                    RemoveEscapes(ref argVal);
 
                    PropertyInfo property = WorkflowMarkupSerializer.LookupProperty(properties, argName);
                    if (property != null)
                    {
                        serializationManager.ContextPush(property);
                        try
                        {
                            DeserializeSimpleProperty(serializationManager, reader, obj, argVal);
                        }
                        finally
                        {
                            Debug.Assert((PropertyInfo)serializationManager.Context.Current == property, "Serializer did not remove an object it pushed into stack.");
                            serializationManager.ContextPop();
                        }
                    }
                    else
                    {
                        serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerPrimitivePropertyNoLogic, new object[] { argName, argName, obj.GetType().FullName }), reader));
                    }
                }
            }
 
            return obj;
        }
 
        // This function splits the argument string into an array of tokens.
        // For example: ID=Workflow1, Path=error1} would become an array that contains the following elements
        // {ID} {=} {Workflwo1} {,} {Path} {=} {error1}
        // Note that the input string should start with the first argument and end with '}'.
        private ArrayList TokenizeAttributes(WorkflowMarkupSerializationManager serializationManager, string args, int lineNumber, int linePosition)
        {
            ArrayList list = null;
            int length = args.Length;
            bool inQuotes = false;
            bool gotEscape = false;
            bool nonWhitespaceFound = false;
            Char quoteChar = '\'';
            int leftCurlies = 0;
            bool collectionIndexer = false;
 
            StringBuilder stringBuilder = null;
            int i = 0;
 
            // Loop through the args, creating a list of arguments and known delimiters.
            // This loop does limited syntax checking, and serves to tokenize the argument
            // string into chunks that are validated in greater detail in the next phase.
            for (; i < length; i++)
            {
                // Escape character is always in effect for everything inside
                // a MarkupExtension.  We have to remember that the next character is 
                // escaped, and is not treated as a quote or delimiter.
                if (!gotEscape && args[i] == '\\')
                {
                    gotEscape = true;
                    continue;
                }
 
                if (!nonWhitespaceFound && !Char.IsWhiteSpace(args[i]))
                {
                    nonWhitespaceFound = true;
                }
 
                // Process all characters that are not whitespace or are between quotes
                if (inQuotes || leftCurlies > 0 || nonWhitespaceFound)
                {
                    // We have a non-whitespace character, so ensure we have
                    // a string builder to accumulate characters and a list to collect
                    // attributes and delimiters.  These are lazily
                    // created so that simple cases that have no parameters do not
                    // create any extra objects.
                    if (stringBuilder == null)
                    {
                        stringBuilder = new StringBuilder(length);
                        list = new ArrayList(1);
                    }
 
                    // If the character is escaped, then it is part of the attribute
                    // being collected, regardless of its value and is not treated as
                    // a delimiter or special character.  Write back the escape
                    // character since downstream processing will need it to determine
                    // whether the value is a MarkupExtension or not, and to prevent
                    // multiple escapes from being lost by recursive processing.
                    if (gotEscape)
                    {
                        stringBuilder.Append('\\');
                        stringBuilder.Append(args[i]);
                        gotEscape = false;
                        continue;
                    }
 
                    // If this characters is not escaped, then look for quotes and
                    // delimiters.
                    if (inQuotes || leftCurlies > 0)
                    {
                        if (inQuotes && args[i] == quoteChar)
                        {
                            // If we're inside quotes, then only an end quote that is not
                            // escaped is special, and will act as a delimiter.
                            inQuotes = false;
                            list.Add(stringBuilder.ToString());
                            stringBuilder.Length = 0;
                            nonWhitespaceFound = false;
                        }
                        else
                        {
                            if (leftCurlies > 0 && args[i] == '}')
                            {
                                leftCurlies--;
                            }
                            else if (args[i] == '{')
                            {
                                leftCurlies++;
                            }
                            stringBuilder.Append(args[i]);
                        }
                    }
                    else
                    {
                        if (args[i] == '"' || args[i] == '\'')
                        {
                            // If we're not inside quotes, then a start quote can only
                            // occur as the first non-whitespace character in a name or value.
                            if (collectionIndexer && i < args.Length - 1 && args[i + 1] == ']')
                            {
                                collectionIndexer = false;
                                stringBuilder.Append(args[i]);
                            }
                            else if (i > 0 && args[i - 1] == '[')
                            {
                                collectionIndexer = true;
                                stringBuilder.Append(args[i]);
                            }
                            else
                            {
                                if (stringBuilder.Length != 0)
                                    return null;
 
                                inQuotes = true;
                                quoteChar = args[i];
                            }
                        }
                        else if (args[i] == ',' || args[i] == '=')
                        {
                            // If there is something in the stringbuilder, then store it
                            if (stringBuilder != null && stringBuilder.Length > 0)
                            {
                                list.Add(stringBuilder.ToString().Trim());
                                stringBuilder.Length = 0;
                            }
                            else if (list.Count == 0 || list[list.Count - 1] is Char)
                            {
                                // Can't have two delimiters in a row, so check what is on
                                // the list and complain if the last item is a character, or if
                                // a delimiter is the first item.
                                return null;
                            }
 
                            // Append known delimiters.
                            list.Add(args[i]);
                            nonWhitespaceFound = false;
                        }
                        else if (args[i] == '}')
                        {
                            // If we hit the outside right curly brace, then end processing.  If
                            // there is a delimiter on the top of the stack and we haven't
                            // hit another non-whitespace character, then its an error
                            if (stringBuilder != null)
                            {
                                if (stringBuilder.Length > 0)
                                {
                                    list.Add(stringBuilder.ToString().Trim());
                                    stringBuilder.Length = 0;
                                }
                                else if (list.Count > 0 && (list[list.Count - 1] is Char))
                                    return null;
                            }
                            break;
                        }
                        else
                        {
                            if (args[i] == '{')
                            {
                                leftCurlies++;
                            }
                            // Must just be a plain old character, so add it to the stringbuilder
                            stringBuilder.Append(args[i]);
                        }
                    }
                }
 
            }
 
 
            // If we've accumulated content but haven't hit a terminating '}' then the
            // format is bad, so complain.
            if (stringBuilder != null && stringBuilder.Length > 0)
                throw new Exception(SR.GetString(SR.Error_MarkupExtensionMissingTerminatingCharacter));
            else if (i < length)
            {
                // If there is non-whitespace text left that we haven't processes yet, 
                // then there is junk after the closing '}', so complain
                for (i = i + 1; i < length; i++)
                {
                    if (!Char.IsWhiteSpace(args[i]))
                        throw new Exception(SR.GetString(SR.Error_ExtraCharacterFoundAtEnd));
                }
            }
 
            return list;
        }
 
        // Remove any '\' escape characters from the passed string.  This does a simple
        // pass through the string and won't do anything if there are no '\' characters.
        private void RemoveEscapes(ref string value)
        {
            StringBuilder builder = null;
            bool noEscape = true;
            for (int i = 0; i < value.Length; i++)
            {
                if (noEscape && value[i] == '\\')
                {
                    if (builder == null)
                    {
                        builder = new StringBuilder(value.Length);
                        builder.Append(value.Substring(0, i));
                    }
                    noEscape = false;
                }
                else if (builder != null)
                {
                    builder.Append(value[i]);
                    noEscape = true;
                }
            }
 
            if (builder != null)
            {
                value = builder.ToString();
            }
        }
        #endregion
 
        #region ContentProperty Support
        private class ContentProperty : IDisposable
        {
            private WorkflowMarkupSerializationManager serializationManager;
            private WorkflowMarkupSerializer parentObjectSerializer;
            private object parentObject;
 
            private PropertyInfo contentProperty;
            private WorkflowMarkupSerializer contentPropertySerializer;
 
            public ContentProperty(WorkflowMarkupSerializationManager serializationManager, WorkflowMarkupSerializer parentObjectSerializer, object parentObject)
            {
                this.serializationManager = serializationManager;
                this.parentObjectSerializer = parentObjectSerializer;
                this.parentObject = parentObject;
 
                this.contentProperty = GetContentProperty(this.serializationManager, this.parentObject);
                if (this.contentProperty != null)
                {
                    this.contentPropertySerializer = this.serializationManager.GetSerializer(this.contentProperty.PropertyType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                    if (this.contentPropertySerializer != null)
                    {
                        try
                        {
                            XmlReader reader = this.serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader;
                            object contentPropertyValue = null;
                            if (reader == null)
                            {
                                contentPropertyValue = this.contentProperty.GetValue(this.parentObject, null);
                            }
                            else if (!this.contentProperty.PropertyType.IsValueType &&
                                    !this.contentProperty.PropertyType.IsPrimitive &&
                                    this.contentProperty.PropertyType != typeof(string) &&
                                    !IsMarkupExtension(this.contentProperty.PropertyType) &&
                                    this.contentProperty.CanWrite)
                            {
                                WorkflowMarkupSerializer serializer = serializationManager.GetSerializer(this.contentProperty.PropertyType, typeof(WorkflowMarkupSerializer)) as WorkflowMarkupSerializer;
                                if (serializer == null)
                                {
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerNotAvailable, this.contentProperty.PropertyType.FullName), reader));
                                    return;
                                }
                                try
                                {
                                    contentPropertyValue = serializer.CreateInstance(serializationManager, this.contentProperty.PropertyType);
                                }
                                catch (Exception e)
                                {
                                    serializationManager.ReportError(CreateSerializationError(SR.GetString(SR.Error_SerializerCreateInstanceFailed, this.contentProperty.PropertyType.FullName, e.Message), reader));
                                    return;
                                }
                                this.contentProperty.SetValue(this.parentObject, contentPropertyValue, null);
                            }
 
                            if (contentPropertyValue != null)
                            {
                                if (reader != null)
                                {
                                    this.contentPropertySerializer.OnBeforeDeserialize(this.serializationManager, contentPropertyValue);
                                    this.contentPropertySerializer.OnBeforeDeserializeContents(this.serializationManager, contentPropertyValue);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e));
                        }
                    }
                    else
                    {
                        this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerNotAvailableForSerialize, this.contentProperty.PropertyType.FullName)));
                    }
                }
            }
 
            void IDisposable.Dispose()
            {
                XmlReader reader = this.serializationManager.WorkflowMarkupStack[typeof(XmlReader)] as XmlReader;
                if (reader != null && this.contentProperty != null && this.contentPropertySerializer != null)
                {
                    try
                    {
                        object contentPropertyValue = this.contentProperty.GetValue(this.parentObject, null);
                        if (contentPropertyValue != null)
                            this.contentPropertySerializer.OnAfterDeserialize(this.serializationManager, contentPropertyValue);
                    }
                    catch (Exception e)
                    {
                        this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e));
                    }
                }
            }
 
            internal PropertyInfo Property
            {
                get
                {
                    return this.contentProperty;
                }
            }
 
            internal object GetContents()
            {
                object value = null;
                if (this.contentProperty != null)
                    value = this.contentProperty.GetValue(this.parentObject, null);
                else
                    value = this.parentObjectSerializer.GetChildren(this.serializationManager, this.parentObject);
                return value;
            }
 
            internal void SetContents(IList<ContentInfo> contents)
            {
                if (contents.Count == 0)
                    return;
 
                if (this.contentProperty == null)
                {
                    int i = 0;
                    try
                    {
                        foreach (ContentInfo contentInfo in contents)
                        {
                            this.parentObjectSerializer.AddChild(this.serializationManager, this.parentObject, contentInfo.Content);
                            i += 1;
                        }
                    }
                    catch (Exception e)
                    {
                        this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[i].LineNumber, contents[i].LinePosition));
                    }
                }
                else if (this.contentPropertySerializer != null)
                {
                    object propertyValue = this.contentProperty.GetValue(this.parentObject, null);
                    if (CollectionMarkupSerializer.IsValidCollectionType(this.contentProperty.PropertyType))
                    {
                        if (propertyValue == null)
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyCanNotBeNull, this.contentProperty.Name, this.parentObject.GetType().FullName)));
                            return;
                        }
 
                        //Notify serializer about begining of deserialization process
                        int i = 0;
                        try
                        {
                            foreach (ContentInfo contentInfo in contents)
                            {
                                this.contentPropertySerializer.AddChild(this.serializationManager, propertyValue, contentInfo.Content);
                                i = i + 1;
                            }
                        }
                        catch (Exception e)
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[i].LineNumber, contents[i].LinePosition));
                        }
                    }
                    else
                    {
                        if (!this.contentProperty.CanWrite)
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyNoSetter, this.contentProperty.Name, this.parentObject.GetType()), contents[0].LineNumber, contents[0].LinePosition));
                            return;
                        }
 
                        if (contents.Count > 1)
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyNoMultipleContents, this.contentProperty.Name, this.parentObject.GetType()), contents[1].LineNumber, contents[1].LinePosition));
 
                        object content = contents[0].Content;
                        if (!this.contentProperty.PropertyType.IsAssignableFrom(content.GetType()) && typeof(string).IsAssignableFrom(content.GetType()))
                        {
                            try
                            {
                                content = this.contentPropertySerializer.DeserializeFromString(this.serializationManager, this.contentProperty.PropertyType, content as string);
                                content = WorkflowMarkupSerializer.GetValueFromMarkupExtension(this.serializationManager, content);
                            }
                            catch (Exception e)
                            {
                                this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[0].LineNumber, contents[0].LinePosition));
                                return;
                            }
                        }
 
                        if (content == null)
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentCanNotBeConverted, content as string, contentProperty.Name, this.parentObject.GetType().FullName, this.contentProperty.PropertyType.FullName), contents[0].LineNumber, contents[0].LinePosition));
                        }
                        else if (!contentProperty.PropertyType.IsAssignableFrom(content.GetType()))
                        {
                            this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyValueInvalid, content.GetType(), this.contentProperty.Name, this.contentProperty.PropertyType.FullName), contents[0].LineNumber, contents[0].LinePosition));
                        }
                        else
                        {
                            try
                            {
                                if (this.contentProperty.PropertyType == typeof(string))
                                {
                                    content = new WorkflowMarkupSerializer().DeserializeFromString(this.serializationManager, this.contentProperty.PropertyType, content as string);
                                    content = WorkflowMarkupSerializer.GetValueFromMarkupExtension(this.serializationManager, content);
                                }
                                this.contentProperty.SetValue(this.parentObject, content, null);
                            }
                            catch (Exception e)
                            {
                                this.serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_SerializerThrewException, this.parentObject.GetType(), e.Message), e, contents[0].LineNumber, contents[0].LinePosition));
                            }
                        }
                    }
                }
            }
 
            private PropertyInfo GetContentProperty(WorkflowMarkupSerializationManager serializationManager, object parentObject)
            {
                PropertyInfo contentProperty = null;
 
                string contentPropertyName = String.Empty;
                object[] contentPropertyAttributes = parentObject.GetType().GetCustomAttributes(typeof(ContentPropertyAttribute), true);
                if (contentPropertyAttributes != null && contentPropertyAttributes.Length > 0)
                    contentPropertyName = ((ContentPropertyAttribute)contentPropertyAttributes[0]).Name;
 
                if (!String.IsNullOrEmpty(contentPropertyName))
                {
                    contentProperty = parentObject.GetType().GetProperty(contentPropertyName, BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public);
                    if (contentProperty == null)
                        serializationManager.ReportError(new WorkflowMarkupSerializationException(SR.GetString(SR.Error_ContentPropertyCouldNotBeFound, contentPropertyName, parentObject.GetType().FullName)));
                }
 
                return contentProperty;
            }
        }
 
        private struct ContentInfo
        {
            public int LineNumber;
            public int LinePosition;
            public object Content;
 
            public ContentInfo(object content, int lineNumber, int linePosition)
            {
                this.Content = content;
                this.LineNumber = lineNumber;
                this.LinePosition = linePosition;
            }
        }
        #endregion
 
        #region MarkupExtension Support
        internal static string EnsureMarkupExtensionTypeName(Type type)
        {
            string extensionName = type.Name;
            if (extensionName.EndsWith(StandardXomlKeys.MarkupExtensionSuffix, StringComparison.OrdinalIgnoreCase))
                extensionName = extensionName.Substring(0, extensionName.Length - StandardXomlKeys.MarkupExtensionSuffix.Length);
            return extensionName;
        }
 
        internal static string EnsureMarkupExtensionTypeName(XmlQualifiedName xmlQualifiedName)
        {
            string typeName = xmlQualifiedName.Name;
            if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal))
            {
                if (typeName.Equals(typeof(Array).Name, StringComparison.Ordinal))
                    typeName = typeof(ArrayExtension).Name;
            }
            return typeName;
        }
 
        private static bool IsMarkupExtension(Type type)
        {
            return (typeof(MarkupExtension).IsAssignableFrom(type) ||
                    typeof(System.Type).IsAssignableFrom(type) ||
                    typeof(System.Array).IsAssignableFrom(type));
        }
 
        private static bool IsMarkupExtension(XmlQualifiedName xmlQualifiedName)
        {
            bool markupExtension = false;
            if (xmlQualifiedName.Namespace.Equals(StandardXomlKeys.Definitions_XmlNs, StringComparison.Ordinal))
            {
                if (xmlQualifiedName.Name.Equals(typeof(Array).Name) || string.Equals(xmlQualifiedName.Name, "Null", StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, typeof(NullExtension).Name, StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, "Type", StringComparison.Ordinal) || string.Equals(xmlQualifiedName.Name, typeof(TypeExtension).Name, StringComparison.Ordinal))
                    markupExtension = true;
            }
            return markupExtension;
        }
 
        private static object GetMarkupExtensionFromValue(object value)
        {
            if (value == null)
                return new NullExtension();
            if (value is System.Type)
                return new TypeExtension(value as System.Type);
            if (value is Array)
                return new ArrayExtension(value as Array);
 
            return value;
        }
 
        private static object GetValueFromMarkupExtension(WorkflowMarkupSerializationManager manager, object extension)
        {
            object value = extension;
            MarkupExtension markupExtension = extension as MarkupExtension;
            if (markupExtension != null)
                value = markupExtension.ProvideValue(manager);
            return value;
        }
        #endregion
    }
    #endregion
}