DataContractSerializer数据不一致下序列化
一、数据类型的等效性
例如下面定义的两个类成员名称、定义顺序都不一样,但是在DataContract、DataMember的Name属性作用下,两个类的实例对象序列化后的xml是一样的,因此Order和OrderV2对于DataContractSerializer序列化是等效的。
[DataContract]
public class Order
{
[DataMember]
public int price; [DataMember(Name = "datev2")]
public DateTime date;
} [DataContract(Name = "Order")]
public class OrderV2
{
[DataMember]
public DateTime datev2; [DataMember(Name = "price")]
public int PriceV2;
}
二、数据添加导致的不一致
假设客户端定义的是OrderLess,服务端定义的是OrderMore。客户端会基于OrderLess进行序列化后发送到服务端。服务端会基于OrderMore反序列化来自客户端的OrderLess序列化后的消息,能序列化成功,但是会发现缺少Name的值。
[DataContract(Name="Order")]
public class OrderLess
{
[DataMember]
public int Price; [DataMember]
public DateTime Date;
} [DataContract(Name = "Order")]
public class OrderMore
{
[DataMember]
public DateTime Date; [DataMember]
public int Price; [DataMember]
public string Name;
}
此时如果我们想对这个缺失的值设置一个默认值,可以通过注册序列化回调方法实现。
OnDeserialized : 在对象反序列化后立即调用。
OnDeserializing :反序列化对象之前调用。
OnSerialized : 在序列化后调用此。
OnSerializing :在序列化前调用。
对OrderMore修改后如下:
[DataContract(Name = "Order")]
public class OrderMore
{
[DataMember]
public DateTime Date; [DataMember]
public int Price; [DataMember]
public string Name; [OnDeserializing]
void OnSerializing(StreamingContext context)
{
this.Name="未指定";
}
}
Main函数:
static void Main(string[] args)
{
OrderLess less=new OrderLess();
less.Date=DateTime.Now;
less.Price=8;
Serialize<OrderLess>(less,@"D:\1.txt");
OrderMore more=null;
DeSerialize<OrderMore>(@"D:\1.txt",out more);
Console.WriteLine("{0} {1} {2}",more.Date,more.Price,more.Name);
}
public static void Serialize<T>(T t, string path)
{
DataContractSerializer ser = new DataContractSerializer(typeof(T));
using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
{
writer.Formatting = Formatting.Indented;
ser.WriteObject(writer, t);
}
}
public static void DeSerialize<T>(string path, out T t)
{
DataContractSerializer ser = new DataContractSerializer(typeof(T));
using (XmlReader reader = new XmlTextReader(path))
{
t = (T)ser.ReadObject(reader);
}
}
输出:
三、数据删除导致的不一致
与二中的交换一下,客户端定义的是OrderMore,服务端定义的是OrderLess。客户端基于OrderMore类型的序列化器序列化OrderMore对象,服务端按基于OrderLess的序列化器反序列化来自客户端的OrderMore的消息。服务端也能序列化成功,但是当服务端将这个对象返回给客户端时,客户端那边会发现少了Name值。为了避免这种情况发生,OrderLess可以实现IExtensibleDataObject接口。作用是将反序列化时未知的数据存放到ExtensionData,再次对这个对象序列化时就可以还原这些未知对象。
对OrderLess进行修改:
[DataContract(Name="Order")]
public class OrderLess:IExtensibleDataObject
{
[DataMember]
public int Price; [DataMember]
public DateTime Date; public ExtensionDataObject ExtensionData
{
get;set;
}
}
Main函数模拟客户端和服务端的交互过程,先序列化OrderMore,再反序列化为OrderLess,此时将未知的Name属性放在OrderLess的ExtensionData。再次序列化这个OrderLess对象。发现1.txt和2.txt的序列化内容是一样的。
static void Main(string[] args)
{
OrderMore more = new OrderMore();
more.Date = DateTime.Now;
more.Price = 8;
more.Name = "OrderMore";
Serialize<OrderMore>(more, @"D:\1.txt"); OrderLess less = null;
DeSerialize<OrderLess>(@"D:\1.txt", out less);
Serialize<OrderLess>(less, @"D:\2.txt");
}
四、数据契约代理
在上述描述都是数据成员添加或删除这种小差异。当两个对象差异很大时(如下面的A和B),却想让两个对象序列化时等效,需要数据契约代理来做一些工作。
[DataContract]
public class A
{
[DataMember]
public string FullName; [DataMember]
public int age;
} [DataContract]
public class B
{
[DataMember]
public string FirstName; [DataMember]
public string LastName; [DataMember]
public int age;
}
MatchA2B实现IDataContractSurrogate接口,在DataContractSerializer序列化过程中能够将一个A对象序列化为B对象,将B对象反序列化为A对象。需要实现GetDataContractType方法,获取需要序列化的实际类型。GetObjectToSerialize序列化前的转换,GetDeserializedObject序列化后的转换。
public class MatchA2B : IDataContractSurrogate
{
public Type GetDataContractType(Type type)
{
return type == typeof(A) ? typeof(B) : type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
A a=obj as A;
if (a != null)
{
B b = new B();
b.age = a.age;
b.FirstName = a.FullName.Split(" ".ToCharArray())[0];
b.LastName = a.FullName.Split(" ".ToCharArray())[1];
return b;
}
return obj;
} public object GetDeserializedObject(object obj, Type targetType)
{
B b = obj as B;
if (b != null)
{
A a = new A();
a.FullName = b.FirstName + " " + b.LastName;
a.age = b.age;
return a;
}
return obj;
}
public object GetCustomDataToExport(Type clrType, Type dataContractType){return null;}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType){return null;}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes){ }
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData){return null;}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{ return null; }
}
Main函数:
class Program
{
static void Main(string[] args)
{
A a = new A();
a.FullName = "Leonardo DiCaprio";
a.age = 41;
Serialize<A>(a, @"D:\1.txt"); A b = null;
DeSerialize<A>(@"D:\1.txt", out b);
Console.WriteLine("{0} {1} ", b.FullName, b.age);
}
public static void Serialize<T>(T t, string path)
{
DataContractSerializer ser = new DataContractSerializer(typeof(T),null,int.MaxValue,false,false,new MatchA2B());
using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
{
writer.Formatting = Formatting.Indented;
ser.WriteObject(writer, t);
}
}
public static void DeSerialize<T>(string path, out T t)
{
DataContractSerializer ser = new DataContractSerializer(typeof(T), null, int.MaxValue, false, false, new MatchA2B());
using (XmlReader reader = new XmlTextReader(path))
{
t = (T)ser.ReadObject(reader);
}
}
}
1.txt中的内容为,成功的将A对象序列化为B:
<B xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication3">
<FirstName>Leonardo</FirstName>
<LastName>DiCaprio</LastName>
<age>41</age>
</B>
DataContractSerializer数据不一致下序列化的更多相关文章
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- Redis面试题记录--缓存双写情况下导致数据不一致问题
转载自:https://blog.csdn.net/lzhcoder/article/details/79469123 https://blog.csdn.net/u013374645/article ...
- 重温WCF之数据契约和序列化(四)
一.数据契约 1.使用数据协定可以灵活控制哪些成员应该被客户端识别. [DataContract] public class Employee { [DataMember] public string ...
- 跟我一起学WCF(7)——WCF数据契约与序列化详解
一.引言 在前面博文介绍到,WCF的契约包括操作契约.数据契约.消息契约和错误契约,前面一篇博文已经结束了操作契约的介绍,接下来自然就是介绍数据契约了.所以本文要分享的内容就是数据契约. 二.数据契约 ...
- WCF分布式开发步步为赢(7):WCF数据契约与序列化
本节继续学习WCF分布式开发步步为赢(7):WCF数据契约与序列化.数据契约是WCF应用程序开发中一个重要的概念,毫无疑问实现客户端与服务端数据契约的传递中序列化是非常重要的步骤.那么序列化是什么?为 ...
- mysql]一次主从数据不一致的问题解决过程()
问题 要解决问题就是怎么对比不一致,然后在不影响业务的情况下,修复数据不一致的问题,把从库缺少的数据补上 下面是能想到和找到的几个方案 1 从新从0开始同步,虽然对主库的使用没有影响,但是那么大的数据 ...
- MySQL主从复制数据不一致问题【自增主键】
前言: 今天遇到主从表不一致的情况,很奇怪为什么会出现不一致的情况,因为复制状态一直都是正常的.最后检查出现不一致的数据都是主键,原来是当时初始化数据的时候导致的.现在分析记录下这个问题,避免以后再遇 ...
- MySQL多字节字符集造成主从数据不一致问题
MySQL多字节字符集造成主从数据不一致问题 来自江羽 2013-04-27 16:03:56| 分类: 默认分类|举报|字号 订阅 转载: http://backend.blog.163.co ...
- [mysql]一次主从数据不一致的问题解决过程
之前一篇: 主从更换ip之后重新建立同步 情况时这样的 昨天晚上主动2个机器都迁移了,然后今天才把主动重新连接上,但是从库的偏移量是从今天当前时刻开始的,也就是说虽然现在主动看似正常,其实是少了昨天的 ...
随机推荐
- SQL Server 维护计划(数据库备份)
公司的项目都需要定期备份,程序备份关掉iis站点复制文件就可以了,难受的地方就是数据库的备份了.服务器上装的大都是英文版,一看见英文,操作都变得小心翼翼起来,生怕哪里搞错,第二天就要被安排写辞职申请了 ...
- BitAdminCore框架更新日志20180529
索引 NET Core应用框架之BitAdminCore框架应用篇系列 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxin/coo ...
- C# 生产成条形码3种方法
首先效果: 1:首先下载BarcodeLib.dll 下载地址 http://pan.baidu.com/share/link?shareid=2590968386&uk=2148890391 ...
- C#多线程编程系列(二)- 线程基础
目录 C#多线程编程系列(二)- 线程基础 1.1 简介 1.2 创建线程 1.3 暂停线程 1.4 线程等待 1.5 终止线程 1.6 检测线程状态 1.7 线程优先级 1.8 前台线程和后台线程 ...
- RabbitMQ广播模式
广播模式:1对多,produce发送一则消息多个consumer同时收到.注意:广播是实时的,produce只负责发出去,不会管对端是否收到,若发送的时刻没有对端接收,那消息就没了,因此在广播模式下设 ...
- s11 day104 数据库表结构与立即支付流程
数据库表结构: 13张 1. 课程大类 2.课程子类 3.学位课程 4.老师表 5.奖学金 6.专题课 7.课程详情 8.课程大纲 9.常见问题 10.章节 11.课时 12.作业表 13.价格策略 ...
- Python中的运算符与表达式
你所编写的大多数语句(逻辑行)都包含了表达式(Expressions).一个表达式的简单例子便是 2+3.表达式可以拆分成运算符(Operators)与操作数(Operands).运算符(Operat ...
- jsp页面,jstl标签中的数据在<%%>java中使用
可参考jsp的API隐式对象.. 这部分数据其实被保存在page域中,但jsp中如果使用java代码需要在特定的标签中<%%>,在这个标签中可使用的只有pageContext对象,所以可以 ...
- 深度了解git工具
今天给大家介绍一个深度了解git的学习视频,视频讲的挺好的,可以听听. 深度了解git学习视频
- django 的ajax 请求,使用form的验证机制。
所有的form都需要在后台验证,前台验证是不可靠的,django的验证是后台验证,前台提示错误信息. js验证是在前台的,无需发送消息给后台,但安全性不可靠,强调的是用户体验. 要求,使用弹出框,弹出 ...