WCF 序列化与反序列化复杂类型.doc_第1页
WCF 序列化与反序列化复杂类型.doc_第2页
WCF 序列化与反序列化复杂类型.doc_第3页
WCF 序列化与反序列化复杂类型.doc_第4页
WCF 序列化与反序列化复杂类型.doc_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

WCF 序列化与反序列化复杂类型(DataContractSerializer)NET的类型可以分为两种:声明类型和真实类型。我们提倡面向接口的编程,对象的真实类型往往需要在运行时才能确定,在编程的时候往往只需要指明类型的声明类型,比如类型实现的接口或者抽象类。当我们使用基于接口或者抽象类创建的DataContractSerializer去序列化一个实现了该接口或者继承该抽象类的实例的时候,往往会因为对对象的真实类型无法识别造成不能正常地序列化。 现在,我们定义两个带数据协定的类ActionInfo和ActionParameterInfo:csharp view plain copy 在CODE上查看代码片派生到我的代码片/ / 动作信息 / DataContract(Namespace = /jiankunking) KnownType(GetKnowTypes) /KnownType(GetKnowTypesQuote) public class ActionInfo private string actionName; / / 动作名称 / DataMember public String ActionName get return actionName; set actionName = value; private string actionId; / / 动作唯一标识 / DataMember public String ActionId get return actionId; set actionId = value; private Dictionary actionParameters; / / 参数信息 / DataMember public Dictionary ActionParameters get if (actionParameters = null) actionParameters = new Dictionary(); return actionParameters; set actionParameters = value; static Type GetKnowTypes() return new Type typeof(Dictionary) ; /DataMember /public object Quote; /static Type GetKnowTypesQuote() / / return new Type typeof(Dictionary) ; / / / 动作参数 / /DataContract(Namespace = /jiankunking) DataContract public class ActionParameterInfo private bool parameterAllowDBNull; / / 参数是否允许为空 / /DataMember(Name = 参数是否允许为空, Order = 2) DataMember public bool ParameterAllowDBNull get return parameterAllowDBNull; set parameterAllowDBNull = value; private ActionInfoParameterCategoryEnum parameterCategory; / / 参数分类 / /DataMember(Name = 参数分类, Order = 3) DataMember public ActionInfoParameterCategoryEnum ParameterCategory get return parameterCategory; set parameterCategory = value; private object parameterValue; / / 参数值 / /DataMember(Name = 参数值, Order = 1) DataMember public object ParameterValue get return parameterValue; set parameterValue = value; private string parameterCode; / / 参数编号(未添加DataMember标识) / 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 在代码中添加以下代码填充实体类:csharp view plain copy 在CODE上查看代码片派生到我的代码片ActionInfo ac = new ActionInfo(); ac.ActionId = ActionId + Guid.NewGuid().ToString(); ac.ActionName = ActionName + Guid.NewGuid().ToString(); ac.ActionParameters = new Dictionary(); 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); 测试序列化:csharp view plain copy 在CODE上查看代码片派生到我的代码片string ss = PubXmlSerializer.ToXMLString(ac); 生成的xml如下:html view plain copy 在CODE上查看代码片派生到我的代码片 ActionIdb9da9159-068e-4cae-9810-5e2ca4f0a87f ActionName70737f3b-1672-437e-8ad5-543038ac62b4 4e059222-023f-40aa-b08e-42e377570092 false CommonType 4e059222-023f-40aa-b08e-42e377570092 5c528920-a7c6-4fc4-8632-a2f083d43676 false CommonType 5c528920-a7c6-4fc4-8632-a2f083d43676 从xml看到:DataContractSerializer在默认的情况下采用了如下的序列化规则。1、XML的根节点名称为数据契约类型的名称。2、默认的命名空间采用的格式为 /2004/07/DataContractSerializerDemo (数据契约类型的命名空间)。3、只有显示地应用了DataMemberAttributue特性的字段或属性才能作为数据成员参与序列化。4、所有数据成员均以XML元素的形式被序列化。5、序列化后数据成员在XML中的次序采用这样的规则:父类数据成员在前,子类数据成员在后;定义在同一个类型中的数据成员按照字母排序。如果默认序列化后的xml结构不能满足我们的需求,则可以通过DataContractAttribute和DataMenmberAttribute这两个特性对其进行修正。在下面我们通过DataContractAttribute特性设置了数据契约的名称和命名空间,通过DataMenmberAttribute特性的Name属性为Name和Birthday两个属性设置不同于属性名称的数据成员名称,并通过Order控制数据成员的先后次序。 修改ActionParameterInfo类:csharp view plain copy 在CODE上查看代码片派生到我的代码片/ / 动作参数 / DataContract(Namespace = /jiankunking) public class ActionParameterInfo private bool parameterAllowDBNull; / / 参数是否允许为空 / DataMember(Name = 参数是否允许为空, Order = 2) public bool ParameterAllowDBNull get return parameterAllowDBNull; set parameterAllowDBNull = value; private ActionInfoParameterCategoryEnum parameterCategory; / / 参数分类 / DataMember(Name = 参数分类, Order = 3) public ActionInfoParameterCategoryEnum ParameterCategory get return parameterCategory; set parameterCategory = value; private object parameterValue; / / 参数值 / DataMember(Name = 参数值, Order = 1) public object ParameterValue get return parameterValue; set parameterValue = value; private string parameterCode; / / 参数编号(未添加DataMember标识) / public string ParameterCode get return parameterCode; set parameterCode = value; 再次序列化,xml结构如下:html view plain copy 在CODE上查看代码片派生到我的代码片 ActionIdd95e434d-4f13-49b7-859e-a7964f468d70 ActionNamef750900a-42fe-4586-9688-768cdefd4d78 560e9e05-2c7d-482a-89f5-ea200bbe42b3 560e9e05-2c7d-482a-89f5-ea200bbe42b3 false CommonType eac9bc48-be0c-4c36-92d0-8f392f010516 eac9bc48-be0c-4c36-92d0-8f392f010516 false CommonType 有木有发现DataMember中Name与Order的作用啊大笑 小注:对于一些比较复杂的类型无法序列化、反序列化(不能识别类型)的时候,就得考虑使用KnownTypeAttribute来标注可能涉及到的外部类型,但如果遇到像泛型这些较为复杂的类型,就要考虑在带数据协定的类中添加一个静态方法,该方法返回Type 的IEnumerable,一般是Type就可以了,而在KnownTypeAttribute的构造函数中使用这个方法的名字。在该demo中将ActionInfo修改为如下形式(即去掉static Type GetKnowTypes()函数,直接标识属性类型)也是可以正常序列化反序列化的:csharp view plain copy 在CODE上查看代码片派生到我的代码片/ / 动作信息 / DataContract(Namespace = /jiankunking) /KnownType(GetKnowTypes) /KnownType(GetKnowTypesQuote) KnownType(typeof(Dictionary) public class ActionInfo private string actionName; / / 动作名称 / DataMember public String ActionName get return actionName; set actionName = value; private string actionId; / / 动作唯一标识 / DataMember public String ActionId get return actionId; set actionId = value; private Dictionary actionParameters; / / 参数信息 / DataMember public Dictionary ActionParameters get if (actionParameters = null) actionParameters = new Dictionary(); return actionParameters; set actionParameters = value; /static Type GetKnowTypes() / / return new Type typeof(Dictionary) ; / /DataMember /public object Quote; /static Type GetKnowTypesQuote() / / return new Type typeof(Dictionary) ; / 修改实体类后的序列化xml如下:html view plain copy 在CODE上查看代码片派生到我的代码片 ActionId394e78b1-0cad-4726-9d6d-6061b7082571 ActionName05ddd5d3-4c08-4bf9-ae7d-2166625dee94 ebb9c44f-69c8-4a52-b59d-7cd8da066591 ebb9c44f-69c8-4a52-b59d-7cd8da066591 false CommonType 1a9f70f8-cf38-4644-a466-6afba99b8837 1a9f70f8-cf38-4644-a466-6afba99b8837 false CommonType 那可不可以去掉KnownType标识呢?答案是不可以的。那么在ActionInfo类中是否可以定义两个已知类型呢?经过测试验证,不能再同一个类中定义两个已知类型,比如:错误信息如下:plain view plain copy 在CODE上查看代码片派生到我的代码片- - 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, Dictionary2 typesChecked, Dictionary2& 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.JsonStringSerializerT(T t) 位置 E:WorkSpaceWorkSpaceTestSerializationDemoSerializationDemoJsonSerializer.cs:行号 29 - 确定 - 但是对于同一个类型,在一个类中可以有多个属性,比如:填充实体类代码如下:csharp view plain copy 在CODE上查看代码片派生到我的代码片ActionInfo ac = new ActionInfo(); ac.ActionId = ActionId + Guid.NewGuid().ToString(); ac.ActionName = ActionName + Guid.NewGuid().ToString(); ac.ActionParameters = new Dictionary(); for (int i = 0; i 2; i+) ActionParameterInfo ap = new ActionParameterInfo(); ap.ParameterAllowDBNull = false; ap.ParameterCategory = ActionInfoParameterCategoryEnum.CommonType; ap.ParameterValue = Guid.NGuid(); ac.ActionParameters.Add(ap.ParameterValue.ToString(), ap); ac.ActionParameters1 = new Dictionary(); for (

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论