WCF 序列化与反序列化复杂类型(DataContractSerializer)

作者:jiankunking 出处:http://blog.csdn.net/jiankunking

.NET的类型可以分为两种:声明类型和真实类型。我们提倡面向接口的编程,对象的真实类型往往需要在运行时才能确定,在编程的时候往往只需要指明类型的声明类型,比如类型实现的接口或者抽象类。当我们使用基于接口或者抽象类创建的DataContractSerializer去序列化一个实现了该接口或者继承该抽象类的实例的时候,往往会因为对对象的真实类型无法识别造成不能正常地序列化。

 现在,我们定义两个带数据协定的类——ActionInfo和ActionParameterInfo:

	/// <summary>
    /// 动作信息
    /// </summary>
    [DataContract(Namespace = "http://blog.csdn.net/jiankunking")]
    [KnownType("GetKnowTypes")]
    //[KnownType("GetKnowTypesQuote")]
    public class ActionInfo
    {
        private string actionName;
        /// <summary>
        /// 动作名称
        /// </summary>
        [DataMember]
        public String ActionName
        {
            get { return actionName; }
            set { actionName = value; }
        }

        private string actionId;
        /// <summary>
        /// 动作唯一标识
        /// </summary>
        [DataMember]
        public String ActionId
        {
            get { return actionId; }
            set { actionId = value; }
        }

        private Dictionary<string, ActionParameterInfo> actionParameters;
        /// <summary>
        /// 参数信息
        /// </summary>
        [DataMember]
        public Dictionary<string, ActionParameterInfo> ActionParameters
        {
            get
            {
                if (actionParameters == null)
                {
                    actionParameters = new Dictionary<string, ActionParameterInfo>();
                }
                return actionParameters;
            }
            set
            {
                actionParameters = value;
            }
        }
        static Type[] GetKnowTypes()
        {
            return new Type[] { typeof(Dictionary<string, ActionParameterInfo>) };
        }

        //[DataMember]
        //public object Quote;

        //static Type[] GetKnowTypesQuote()
        //{
        //    return new Type[] { typeof(Dictionary<string, int>) };
        //}
    }
	 /// <summary>
    /// 动作参数
    /// </summary>
    //[DataContract(Namespace = "http://blog.csdn.net/jiankunking")]
    [DataContract]
    public class ActionParameterInfo
    {
        private bool parameterAllowDBNull;
        /// <summary>
        /// 参数是否允许为空
        /// </summary>
        //[DataMember(Name = "参数是否允许为空", Order = 2)]
        [DataMember]
        public bool ParameterAllowDBNull
        {
            get { return parameterAllowDBNull; }
            set { parameterAllowDBNull = value; }
        }

        private ActionInfoParameterCategoryEnum parameterCategory;
        /// <summary>
        /// 参数分类
        /// </summary>
        //[DataMember(Name = "参数分类", Order = 3)]
        [DataMember]
        public ActionInfoParameterCategoryEnum ParameterCategory
        {
            get { return parameterCategory; }
            set { parameterCategory = value; }
        }

        private object parameterValue;
        /// <summary>
        /// 参数值
        /// </summary>
        //[DataMember(Name = "参数值", Order = 1)]
        [DataMember]
        public object ParameterValue
        {
            get { return parameterValue; }
            set { parameterValue = value; }
        }

        private string parameterCode;
        /// <summary>
        /// 参数编号(未添加DataMember标识)
        /// </summary>
        public string ParameterCode
        {
            get { return parameterCode; }
            set { parameterCode = value; }
        }
	 public enum ActionInfoParameterCategoryEnum
     {
        [Description("普通类型")]
        CommonType = 0,
        [Description("事件源")]
        EventSource = 1,
        [Description("事件参数")]
        EventArgument = 2,
        [Description("控件ID")]
        ControlId = 3,
        [Description("表单ID")]
        FormId = 4
     }

在代码中添加以下代码填充实体类:

 ActionInfo ac = new ActionInfo();
            ac.ActionId = "ActionId" + Guid.NewGuid().ToString();
            ac.ActionName = "ActionName" + Guid.NewGuid().ToString();
            ac.ActionParameters = new Dictionary<string, ActionParameterInfo>();
            for (int i = 0; i < 2; i++)
            {
                ActionParameterInfo ap = new ActionParameterInfo();
                ap.ParameterAllowDBNull = false;
                ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType;
                ap.ParameterValue = Guid.NewGuid();
                ac.ActionParameters.Add(ap.ParameterValue.ToString(), ap);
            }

      测试序列化:

 string ss = PubXmlSerializer<ActionInfo>.ToXMLString(ac);

生成的xml如下:

<ActionInfo xmlns="http://blog.csdn.net/jiankunking" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<ActionId>ActionIdb9da9159-068e-4cae-9810-5e2ca4f0a87f</ActionId>
	<ActionName>ActionName70737f3b-1672-437e-8ad5-543038ac62b4</ActionName>
	<ActionParameters xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringActionParameterInfo0UA3f0ok>
			<a:Key>4e059222-023f-40aa-b08e-42e377570092</a:Key>
			<a:Value xmlns:b="http://schemas.datacontract.org/2004/07/SerializationDemo">
				<b:ParameterAllowDBNull>false</b:ParameterAllowDBNull>
				<b:ParameterCategory>CommonType</b:ParameterCategory>
				<b:ParameterValue i:type="c:guid" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/">4e059222-023f-40aa-b08e-42e377570092</b:ParameterValue>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfo0UA3f0ok>
		<a:KeyValueOfstringActionParameterInfo0UA3f0ok>
			<a:Key>5c528920-a7c6-4fc4-8632-a2f083d43676</a:Key>
			<a:Value xmlns:b="http://schemas.datacontract.org/2004/07/SerializationDemo">
				<b:ParameterAllowDBNull>false</b:ParameterAllowDBNull>
				<b:ParameterCategory>CommonType</b:ParameterCategory>
				<b:ParameterValue i:type="c:guid" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/">5c528920-a7c6-4fc4-8632-a2f083d43676</b:ParameterValue>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfo0UA3f0ok>
	</ActionParameters>
</ActionInfo>

  从xml看到:

DataContractSerializer在默认的情况下采用了如下的序列化规则。
1、XML的根节点名称为数据契约类型的名称。
2、默认的命名空间采用的格式为  http://schemas.datacontract.org/2004/07/DataContractSerializerDemo (数据契约类型的命名空间)。
3、只有显示地应用了DataMemberAttributue特性的字段或属性才能作为数据成员参与序列化。
4、所有数据成员均以XML元素的形式被序列化。
5、序列化后数据成员在XML中的次序采用这样的规则:父类数据成员在前,子类数据成员在后;定义在同一个类型中的数据成员按照字母排序。

如果默认序列化后的xml结构不能满足我们的需求,则可以通过DataContractAttribute和DataMenmberAttribute这两个特性对其进行修正。在下面我们通过DataContractAttribute特性设置了数据契约的名称和命名空间,通过DataMenmberAttribute特性的Name属性为Name和Birthday两个属性设置不同于属性名称的数据成员名称,并通过Order控制数据成员的先后次序。

   修改ActionParameterInfo类:

    /// <summary>
    /// 动作参数
    /// </summary>
    [DataContract(Namespace = "http://blog.csdn.net/jiankunking")]
    public class ActionParameterInfo
    {
        private bool parameterAllowDBNull;
        /// <summary>
        /// 参数是否允许为空
        /// </summary>
        [DataMember(Name = "参数是否允许为空", Order = 2)]
        public bool ParameterAllowDBNull
        {
            get { return parameterAllowDBNull; }
            set { parameterAllowDBNull = value; }
        }

        private ActionInfoParameterCategoryEnum parameterCategory;
        /// <summary>
        /// 参数分类
        /// </summary>
        [DataMember(Name = "参数分类", Order = 3)]
        public ActionInfoParameterCategoryEnum ParameterCategory
        {
            get { return parameterCategory; }
            set { parameterCategory = value; }
        }

        private object parameterValue;
        /// <summary>
        /// 参数值
        /// </summary>
        [DataMember(Name = "参数值", Order = 1)]
        public object ParameterValue
        {
            get { return parameterValue; }
            set { parameterValue = value; }
        }

        private string parameterCode;
        /// <summary>
        /// 参数编号(未添加DataMember标识)
        /// </summary>
        public string ParameterCode
        {
            get { return parameterCode; }
            set { parameterCode = value; }
        }

再次序列化,xml结构如下:

<ActionInfo xmlns="http://blog.csdn.net/jiankunking" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<ActionId>ActionIdd95e434d-4f13-49b7-859e-a7964f468d70</ActionId>
	<ActionName>ActionNamef750900a-42fe-4586-9688-768cdefd4d78</ActionName>
	<ActionParameters xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>560e9e05-2c7d-482a-89f5-ea200bbe42b3</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">560e9e05-2c7d-482a-89f5-ea200bbe42b3</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>eac9bc48-be0c-4c36-92d0-8f392f010516</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">eac9bc48-be0c-4c36-92d0-8f392f010516</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
	</ActionParameters>
</ActionInfo>

有木有发现DataMember中Name与Order的作用啊

        小注:

对于一些比较复杂的类型无法序列化、反序列化(不能识别类型)的时候,就得考虑使用KnownTypeAttribute来标注可能涉及到的外部类型,但如果遇到像泛型这些较为复杂的类型,就要考虑在带数据协定的类中添加一个静态方法,该方法返回Type 的IEnumerable,一般是Type[]就可以了,而在KnownTypeAttribute的构造函数中使用这个方法的名字。

在该demo中将ActionInfo修改为如下形式(即去掉static Type[] GetKnowTypes()函数,直接标识属性类型)也是可以正常序列化反序列化的:

/// <summary>
    /// 动作信息
    /// </summary>
    [DataContract(Namespace = "http://blog.csdn.net/jiankunking")]
    //[KnownType("GetKnowTypes")]
    //[KnownType("GetKnowTypesQuote")
    [KnownType(typeof(Dictionary<string, ActionParameterInfo>))]
    public class ActionInfo
    {
        private string actionName;
        /// <summary>
        /// 动作名称
        /// </summary>
        [DataMember]
        public String ActionName
        {
            get { return actionName; }
            set { actionName = value; }
        }

        private string actionId;
        /// <summary>
        /// 动作唯一标识
        /// </summary>
        [DataMember]
        public String ActionId
        {
            get { return actionId; }
            set { actionId = value; }
        }

        private Dictionary<string, ActionParameterInfo> actionParameters;
        /// <summary>
        /// 参数信息
        /// </summary>
        [DataMember]
        public Dictionary<string, ActionParameterInfo> ActionParameters
        {
            get
            {
                if (actionParameters == null)
                {
                    actionParameters = new Dictionary<string, ActionParameterInfo>();
                }
                return actionParameters;
            }
            set
            {
                actionParameters = value;
            }
        }
        //static Type[] GetKnowTypes()
        //{
        //    return new Type[] { typeof(Dictionary<string, ActionParameterInfo>) };
        //}

        //[DataMember]
        //public object Quote;

        //static Type[] GetKnowTypesQuote()
        //{
        //    return new Type[] { typeof(Dictionary<string, int>) };
        //}
    }

修改实体类后的序列化xml如下:

<ActionInfo xmlns="http://blog.csdn.net/jiankunking" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<ActionId>ActionId394e78b1-0cad-4726-9d6d-6061b7082571</ActionId>
	<ActionName>ActionName05ddd5d3-4c08-4bf9-ae7d-2166625dee94</ActionName>
	<ActionParameters xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">

		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>ebb9c44f-69c8-4a52-b59d-7cd8da066591</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">ebb9c44f-69c8-4a52-b59d-7cd8da066591</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>

		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>1a9f70f8-cf38-4644-a466-6afba99b8837</a:Key>

			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">1a9f70f8-cf38-4644-a466-6afba99b8837</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>

		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
	</ActionParameters>
</ActionInfo>

  那可不可以去掉KnownType标识呢?答案是不可以的。

那么在ActionInfo类中是否可以定义两个已知类型呢?

经过测试验证,不能再同一个类中定义两个已知类型,比如:

同时在类上标识:

错误信息如下:

---------------------------
---------------------------
System.Runtime.Serialization.InvalidDataContractException: 类型“SerializationDemo.ActionInfo”的 KnownTypeAttribute 特性指定一个名为“GetKnowTypes”的方法,以提供已知类型。此类型上找不到静态方法“GetKnowTypes()”。请确保此方法存在并标记为静态。
   在 System.Runtime.Serialization.DataContract.DataContractCriticalHelper.ThrowInvalidDataContractException(String message, Type type)
   在 System.Runtime.Serialization.DataContract.ImportKnownTypeAttributes(Type type, Dictionary`2 typesChecked, Dictionary`2& knownDataContracts)
   在 System.Runtime.Serialization.DataContract.ImportKnownTypeAttributes(Type type)
   在 System.Runtime.Serialization.ClassDataContract.ClassDataContractCriticalHelper.get_KnownDataContracts()
   在 System.Runtime.Serialization.ClassDataContract.get_KnownDataContracts()
   在 System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
   在 System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph)
   在 System.Runtime.Serialization.Json.DataContractJsonSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph)
   在 System.Runtime.Serialization.XmlObjectSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   在 System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
   在 System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
   在 System.Runtime.Serialization.Json.DataContractJsonSerializer.WriteObject(Stream stream, Object graph)
   在 SerializationDemo.JsonSerializer.JsonStringSerializer[T](T t) 位置 E:\WorkSpace\WorkSpaceTest\SerializationDemo\SerializationDemo\JsonSerializer.cs:行号 29
---------------------------
确定
---------------------------

但是对于同一个类型,在一个类中可以有多个属性,比如:

   

填充实体类代码如下:

 ActionInfo ac = new ActionInfo();
            ac.ActionId = "ActionId" + Guid.NewGuid().ToString();
            ac.ActionName = "ActionName" + Guid.NewGuid().ToString();
            ac.ActionParameters = new Dictionary<string, ActionParameterInfo>();
            for (int i = 0; i < 2; i++)
            {
                ActionParameterInfo ap = new ActionParameterInfo();
                ap.ParameterAllowDBNull = false;
                ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType;
                ap.ParameterValue = Guid.NewGuid();
                ac.ActionParameters.Add(ap.ParameterValue.ToString(), ap);
            }
            ac.ActionParameters1 = new Dictionary<string, ActionParameterInfo>();
            for (int i = 0; i < 2; i++)
            {
                ActionParameterInfo ap = new ActionParameterInfo();
                ap.ParameterAllowDBNull = false;
                ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType;
                ap.ParameterValue = Guid.NewGuid();
                ac.ActionParameters1.Add(ap.ParameterValue.ToString(), ap);
            }

序列化之后的xml如下:

<ActionInfo xmlns="http://blog.csdn.net/jiankunking" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<ActionId>ActionIded35fdb5-0c47-440e-9d6e-8dba364d49d5</ActionId>
	<ActionName>ActionNamef991e495-7cc2-43a2-863f-4a9c139641b1</ActionName>
	<ActionParameters xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>aec5004a-79d3-4949-8c70-eb7605aa6702</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">aec5004a-79d3-4949-8c70-eb7605aa6702</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>d859df4f-1b82-4144-9f1b-3a4c01ff1a10</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">d859df4f-1b82-4144-9f1b-3a4c01ff1a10</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
	</ActionParameters>
	<ActionParameters1 xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>110478a6-a177-4dec-bc7f-77027bd30bd3</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">110478a6-a177-4dec-bc7f-77027bd30bd3</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>cdf8d367-dac4-4ae0-a6b7-d3de0f9fc92a</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">cdf8d367-dac4-4ae0-a6b7-d3de0f9fc92a</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
	</ActionParameters1>
</ActionInfo>

如果就是有多个复杂属性如何处理呢?

铛铛==》

 [KnownType(typeof(Dictionary<string, ActionParameterInfo>))]
    [KnownType(typeof(Dictionary<string, int>))]

        修改ActionInfo类为:

 /// <summary>
    /// 动作信息
    /// </summary>
    [DataContract(Namespace = "http://blog.csdn.net/jiankunking")]
    //[KnownType("GetKnowTypes")]
    //[KnownType("GetKnowTypesQuote")]
    //[KnownType(typeof(Dictionary<string, ActionParameterInfo>))]

    [KnownType(typeof(Dictionary<string, ActionParameterInfo>))]
    [KnownType(typeof(Dictionary<string, int>))]
    public class ActionInfo
    {
        private string actionName;
        /// <summary>
        /// 动作名称
        /// </summary>
        [DataMember]
        public String ActionName
        {
            get { return actionName; }
            set { actionName = value; }
        }

        private string actionId;
        /// <summary>
        /// 动作唯一标识
        /// </summary>
        [DataMember]
        public String ActionId
        {
            get { return actionId; }
            set { actionId = value; }
        }

        private Dictionary<string, ActionParameterInfo> actionParameters;
        /// <summary>
        /// 参数信息
        /// </summary>
        [DataMember]
        public Dictionary<string, ActionParameterInfo> ActionParameters
        {
            get
            {
                if (actionParameters == null)
                {
                    actionParameters = new Dictionary<string, ActionParameterInfo>();
                }
                return actionParameters;
            }
            set
            {
                actionParameters = value;
            }
        }
        //private Dictionary<string, ActionParameterInfo> actionParameters1;
        ///// <summary>
        ///// 参数信息
        ///// </summary>
        //[DataMember]
        //public Dictionary<string, ActionParameterInfo> ActionParameters1
        //{
        //    get
        //    {
        //        if (actionParameters1 == null)
        //        {
        //            actionParameters1 = new Dictionary<string, ActionParameterInfo>();
        //        }
        //        return actionParameters1;
        //    }
        //    set
        //    {
        //        actionParameters1 = value;
        //    }
        //}
        //static Type[] GetKnowTypes()
        //{
        //    return new Type[] { typeof(Dictionary<string, ActionParameterInfo>) };
        //}

        [DataMember]
        public Dictionary<string, int> Quote = new Dictionary<string, int>();

        //static Type[] GetKnowTypesQuote()
        //{
        //    return new Type[] { typeof(Dictionary<string, int>) };
        //}
    }

      填充实体的代码如下:

            ActionInfo ac = new ActionInfo();
            ac.ActionId = "ActionId" + Guid.NewGuid().ToString();
            ac.ActionName = "ActionName" + Guid.NewGuid().ToString();
            ac.ActionParameters = new Dictionary<string, ActionParameterInfo>();
            for (int i = 0; i < 2; i++)
            {
                ActionParameterInfo ap = new ActionParameterInfo();
                ap.ParameterAllowDBNull = false;
                ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType;
                ap.ParameterValue = Guid.NewGuid();
                ac.ActionParameters.Add(ap.ParameterValue.ToString(), ap);
            }
            //ac.ActionParameters1 = new Dictionary<string, ActionParameterInfo>();
            //for (int i = 0; i < 2; i++)
            //{
            //    ActionParameterInfo ap = new ActionParameterInfo();
            //    ap.ParameterAllowDBNull = false;
            //    ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType;
            //    ap.ParameterValue = Guid.NewGuid();
            //    ac.ActionParameters1.Add(ap.ParameterValue.ToString(), ap);
            //}

            ac.Quote = new Dictionary<string, int>();
            for (int i = 0; i < 2; i++)
            {
                string str = Guid.NewGuid().ToString();
                int f = i;
                ((Dictionary<string, int>)ac.Quote).Add(str, f);
            }

       序列化之后的结果为:

<ActionInfo xmlns="http://blog.csdn.net/jiankunking" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
	<ActionId>ActionIdb4df91db-7ba1-480f-bc6f-2dfa3eb27ae7</ActionId>
	<ActionName>ActionName30be2364-53d6-429d-8ca4-61dd8928b779</ActionName>
	<ActionParameters xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>240b226f-8aa0-48e7-a24f-0640e2da7172</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">240b226f-8aa0-48e7-a24f-0640e2da7172</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
		<a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
			<a:Key>73085803-8d35-4b52-a550-c354f0dae7a0</a:Key>
			<a:Value>
				<参数值 i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">73085803-8d35-4b52-a550-c354f0dae7a0</参数值>
				<参数是否允许为空>false</参数是否允许为空>
				<参数分类>CommonType</参数分类>
			</a:Value>
		</a:KeyValueOfstringActionParameterInfoKdFY_PqWd>
	</ActionParameters>
	<Quote xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
		<a:KeyValueOfstringint>
			<a:Key>d9298e16-e41f-4508-a7dc-6a26e137ec2d</a:Key>
			<a:Value>0</a:Value>
		</a:KeyValueOfstringint>
		<a:KeyValueOfstringint>
			<a:Key>1a53f746-60fe-4b0b-8c48-479693ad46fa</a:Key>
			<a:Value>1</a:Value>
		</a:KeyValueOfstringint>
	</Quote>
</ActionInfo>

           可见,可以通过多个KnownType标识来实现同一个数据契约中多个复杂类型的序列化与反序列化。

此处是以两个字典类型来验证的,其实不管是list还是字典都可以通过:多个KnownType标识来实现同一个数据契约中多个复杂类型的序列化与反序列化。 

KnownType标识类简洁处理方式(这种方式不需要在类上标识KnownType):

List<Type> knownTypes = new List<Type>();
knownTypes.Add(typeof(Dictionary<string, ActionParameterInfo>));
knownTypes.Add(typeof(List<ActionParameterInfo>));

       然后调用:

DataContractSerializer<ActionInfo>.ToXMLString(ac, knownTypes);

         即可

  序列化反序列化代码:点击打开链接

       Demo代码下载:点击打开链接

  DataContractJsonSerializer的用法与DataContractSerializer类似,只是两者对于实体类序列化后的存储形式不一样,仅此而已。

C# WCF DataContractSerializer 类

小注:

如果序列化list<baseclass>即需要序列化一个由baseclass类及其子类组成的集合的时候,需要在子类基类上加上标识

[KnownType(typeof(EndEvent))]
public class EndEvent:BpmnEvent

在反序列化的时候,调用:

 public static T ReadFromXML(string xmlStr, IEnumerable<Type> knownTypes = null) 

 传入子类基类的的Type

参考文章:

WCF学习笔记——对象序列化

传说中的WCF(6):数据协定(b)

序列化和反序列化的几种方式(DataContractSerializer)(二)

关于复杂类型的序列化 

时间: 2024-08-30 17:19:49

WCF 序列化与反序列化复杂类型(DataContractSerializer)的相关文章

XmlSerializer 对象的Xml序列化和反序列化

try { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("my", "http://flibble"); Workers workers = new Workers(); workers.MyWorkers = new Worker[] { new Worker() { Name = "1", Number = 1 }, new Worker() { Nam

序列化和反序列化的几种方式(DataContractSerializer)(二)

DataContractSerializer 类      使用提供的数据协定,将类型实例序列化和反序列化为 XML 流或文档. 无法继承此类. 命名空间: System.Runtime.Serialization程序集:  System.Runtime.Serialization(在 System.Runtime.Serialization.dll 中) 备注      使用 DataContractSerializer 类可以将类型实例序列化和反序列化为 XML 流或文档. 通过将 Data

序列化和反序列化,异步调用web/wcf/函数

//xml序列化 public static string Seria(DataSet ds) { XmlSerializer serializer = new XmlSerializer(typeof(DataSet)); StringBuilder sb = new StringBuilder(); XmlWriter writer = XmlWriter.Create(sb); serializer.Serialize(writer, ds); return sb.ToString();

Windows 8 Store Apps学习(60) 通信: 获取网络信息, 序列化和反序列化

介绍 重新想象 Windows 8 Store Apps 之 通信 获取网络信息 序列化 - json 序列化 - xml 序列化 - rss atom 示例 1.演示如何获取网络的相关信息 Communication/NetworkInfo.xaml.cs /* * 演示如何获取网络的相关信息 */ using System; using System.Collections.Generic; using Windows.Networking.Connectivity; using Windo

重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化

原文:重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化 [源码下载] 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 获取网络信息 序列化 - json 序列化 - xml 序列化 - rss atom 示例1.演示如何获取网络的相关信息Communication/NetworkInfo.xa

ASP.NET中JSON的序列化和反序列化

导读:JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍,ASP.NET如何序列化和反序列化的处理,在序列化和反序列化对日期时间.集合.字典的处理. 一.JSON简介 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式. JSON是"名值对"的集合.结构由大括号'{

WPF 字体、颜色等属性的序列化和反序列化

WPF自带的一些属性比如System.Windows.Media.Brush.System.Windows.Media.FontFamily.System.Windows.FontWeight等不具有直接序列化能力,本文针对这一点设计名为PropertySerializateDictionary的类,实现了不同类不同对象公有属性的序列化和反序列化.本类继承于Dictionary<string, TypeAndValue>, IXmlSerializable,调用了自实现类TypeAndValu

序列化和反序列化技术在编写Socket应用程序时的应用

我们在编写与Socket有关的应用程序时,在发送软为复杂的数据时,可能我们最常做的是把各个部分的数据转换为字符串,然后将这些字符串用一个分隔符连接起来进行发送.不过,不知道你有没有想过这样做还是有问题的. 比如,我用#来分隔各个字符串,在根据客户端输入的内容到服务器端进行查找,然后返回结果,万一用户输入的查找关键字中就包含#,那么就会影响我们对字符串进行分割了. 不知道各位有没有想过,把序列化和反序列化的技术也用到socket上?先定义一个封装数据的类,发送前将该类的对象序列化,然后发送:接收时

详解Python中的序列化与反序列化的使用

  这篇文章主要介绍了详解Python中的序列化与反序列化的使用,针对pickle和cPickle对象进行了探究,需要的朋友可以参考下 学习过marshal模块用于序列化和反序列化,但marshal的功能比较薄弱,只支持部分内置数据类型的序列化/反序列化,对于用户自定义的类型就无能为力,同时marshal不支持自引用(递归引用)的对象的序列化.所以直接使用marshal来序列化/反序列化可能不是很方便.还好,python标准库提供了功能更加强大且更加安全的pickle和cPickle模块. cP