File: AuthoringOM\Serializer\PropertySegmentSerializer.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
namespace System.Workflow.ComponentModel.Serialization
{
    using System;
    using System.Reflection;
    using System.Xml;
    using System.ComponentModel.Design.Serialization;
    using System.Collections;
    using System.Workflow.ComponentModel.Design;
    using System.ComponentModel;
 
    #region Class PropertySegmentSerializer
    internal sealed class PropertySegmentSerializer : WorkflowMarkupSerializer
    {
        private WorkflowMarkupSerializer containedSerializer = null;
        public PropertySegmentSerializer(WorkflowMarkupSerializer containedSerializer)
        {
            this.containedSerializer = containedSerializer;
        }
 
        protected internal override PropertyInfo[] GetProperties(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (this.containedSerializer != null)
                return this.containedSerializer.GetProperties(serializationManager, obj);
 
            if (obj != null && obj.GetType() == typeof(PropertySegment))
                return (obj as PropertySegment).GetProperties(serializationManager);
            else
                return base.GetProperties(serializationManager, obj);
        }
 
        protected override object CreateInstance(WorkflowMarkupSerializationManager serializationManager, Type type)
        {
            if (typeof(PropertySegment) == type)
                // This is a "safe" Activiator.CreateInstance because we know we are creating an instance of PropertySegment, which is an internal sealed class.
                return Activator.CreateInstance(type, new object[] { serializationManager as IServiceProvider, serializationManager.Context.Current });
            else
                return base.CreateInstance(serializationManager, type);
        }
 
        protected internal override bool ShouldSerializeValue(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            return true;
        }
 
        protected internal override bool CanSerializeToString(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            bool canSerializeToString = false;
            if (value != null)
            {
                ITypeDescriptorContext context = null;
                TypeConverter converter = GetTypeConversionInfoForPropertySegment(serializationManager, value.GetType(), out context);
                if (converter != null)
                    canSerializeToString = converter.CanConvertTo(context, typeof(string));
 
                if (!canSerializeToString)
                {
                    if (this.containedSerializer != null)
                        canSerializeToString = this.containedSerializer.CanSerializeToString(serializationManager, value);
                    else
                        canSerializeToString = base.CanSerializeToString(serializationManager, value);
                }
            }
            else
            {
                canSerializeToString = true;
            }
 
            return canSerializeToString;
        }
 
        protected internal override string SerializeToString(WorkflowMarkupSerializationManager serializationManager, object value)
        {
            String stringValue = String.Empty;
            if (value == null)
            {
                stringValue = "*null";
            }
            else
            {
                ITypeDescriptorContext context = null;
                TypeConverter converter = GetTypeConversionInfoForPropertySegment(serializationManager, value.GetType(), out context);
                if (converter != null && converter.CanConvertTo(context, typeof(string)))
                    stringValue = converter.ConvertToString(context, value);
                else if (this.containedSerializer != null)
                    stringValue = this.containedSerializer.SerializeToString(serializationManager, value);
                else
                    stringValue = base.SerializeToString(serializationManager, value);
            }
 
            return stringValue;
        }
 
        protected internal override object DeserializeFromString(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 convertedValue = null;
            if (string.Equals(value, "*null", StringComparison.Ordinal))
            {
                convertedValue = null;
            }
            else
            {
                ITypeDescriptorContext context = null;
                TypeConverter converter = GetTypeConversionInfoForPropertySegment(serializationManager, propertyType, out context);
                if (converter != null && converter.CanConvertFrom(context, typeof(string)))
                    convertedValue = converter.ConvertFromString(context, value);
                else if (this.containedSerializer != null)
                    convertedValue = this.containedSerializer.DeserializeFromString(serializationManager, propertyType, value);
                else
                    convertedValue = base.DeserializeFromString(serializationManager, propertyType, value);
            }
 
            return convertedValue;
        }
 
        protected internal override IList GetChildren(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (this.containedSerializer != null)
                return this.containedSerializer.GetChildren(serializationManager, obj);
 
            return null;
        }
 
        protected internal override void ClearChildren(WorkflowMarkupSerializationManager serializationManager, object obj)
        {
            if (this.containedSerializer != null)
                this.containedSerializer.ClearChildren(serializationManager, obj);
        }
 
        protected internal override void AddChild(WorkflowMarkupSerializationManager serializationManager, object obj, object childObj)
        {
            if (this.containedSerializer != null)
                this.containedSerializer.AddChild(serializationManager, obj, childObj);
        }
 
        private TypeConverter GetTypeConversionInfoForPropertySegment(WorkflowMarkupSerializationManager serializationManager, Type propertyType, out ITypeDescriptorContext context)
        {
            TypeConverter converter = null;
            context = null;
            PropertySegmentPropertyInfo propertyInfo = serializationManager.Context[typeof(PropertySegmentPropertyInfo)] as PropertySegmentPropertyInfo;
            if (propertyInfo.PropertySegment != null)
            {
                if (propertyInfo.PropertySegment.PropertyDescriptor != null)
                {
                    context = new TypeDescriptorContext(propertyInfo.PropertySegment.ServiceProvider, propertyInfo.PropertySegment.PropertyDescriptor, propertyInfo.PropertySegment.Object);
                    converter = propertyInfo.PropertySegment.PropertyDescriptor.Converter;
                }
                else if (propertyInfo.PropertySegment.Object != null)
                {
                    PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties(propertyInfo.PropertySegment.Object)[propertyInfo.Name];
                    if (propertyDescriptor != null)
                    {
                        context = new TypeDescriptorContext(propertyInfo.PropertySegment.ServiceProvider, propertyDescriptor, propertyInfo.PropertySegment.Object);
                        converter = propertyDescriptor.Converter;
                    }
                }
            }
 
            if (propertyType != null && converter == null)
            {
                converter = TypeDescriptor.GetConverter(propertyType);
            }
 
            return converter;
        }
    }
    #endregion
}