首页 > 不同命名空间的对象二进制反序列化问题

不同命名空间的对象二进制反序列化问题

 本质上说,这并不是二进制序列化的问题,甚至不关序列化的问题。

  你想要的是在两个内部结构一致但在不同命名空间(甚至不同项目)的同名类间做类型转换。

 

  这个问题很常见,因为实际工作中经常会有此类需求,但是我们又不可能手动的把每个字段的值都抄来抄去。

 

  解决此问题的方法很多,但都逃不开一个关键思想:A不知道B的存在,B不知道A的存在,那么我就找出一个C,只要A和B都能以C的形式表示,那么转换就不是问题。这里的C是概念上的一个标准,用于当做A和B转换的桥梁。

 

  普遍的解决方法:

  1. 如一楼所说,XmlSerializer序列化器能够将一个可Xml序列化的类A的“内容”部分抽取出来序列化成Xml片段,也能够将其反序列化为一个符合该Xml“格式”的类B。代码如下。

    序列化端:

1
2
3
4
5
6
7
8
System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(classA));
System.IO.Stream stream = new System.IO.FileStream(@"c: mp.txt",System.IO.FileMode.OpenOrCreate);
xs.Serialize(stream, new classA { i = 10, s = "hello" });
stream.Dispose();
反序列化端:
 System.Xml.Serialization.XmlSerializer xsb = new System.Xml.Serialization.XmlSerializer(typeof(classA));
 classA b = (classA)xsb.Deserialize(new System.IO.FileStream(@"c: mp.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read));

打开c: mp.txt,我们可以看到中间传输的内容是

1
2
3
4
5
"1.0"?>
"http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  10
  hello

这表明了传输的内容只关注类名和共有属性/字段。所以在反序列化端,只要我们有同样结构的同名类classA,是可以直接从Xml流进行转换的。当然使用内存流、字节流等都是可以的。这里一定要切记三点:同名同结构(指共有字段/属性部分)的两个类,以及只能序列化公有字段和属性,两个类都必须有默认构造方法。

 

Xml序列化的优点在于只序列化必要部分且消耗较少,常用于序列化DataTable等结构。

 

2.第二种方法是使用接口。也许你的两个类分处不同的命名空间或者不同项目,但是只要都能访问到同一interface,那么我们可以稍微费点功夫写一个两个都“认识”的接口,通过接口来转换对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface dataInterface
    {
        int i{ get;set;}
        string s{ get;set;}
    }
    [Serializable]
    public class classA : dataInterface
    {
        public int i{ get;set;}
        public string s{ get;set;}
    }
    [Serializable]
    public class classB : dataInterface
    {
        public int i{ get;set}
        public string s{ get;set;}
    }

如此,不管classA和classB在哪里,只要你认得dataInterface,那么就可以用其来传输、访问和转换。传输的过程相比xml序列化就灵活多了,你可以使用socket、文件、消息、甚至共享内存等等手段来传输,序列化也可以使用万能的二进制序列化,因为你传出和接受的,都是dataInterface对象而已。

 

序列化端(二进制序列化+文件传输举例):

1
2
3
4
 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            System.IO.FileStream fs = new System.IO.FileStream(@"c: mp", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
            formatter.Serialize(fs, (new classA { i = 10, s = "hello" }));
            fs.Dispose();

反序列化:

 

1
dataInterface data = (dataInterface)formatter.Deserialize(new System.IO.FileStream(@"c: mp", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read));

此方法优缺点显而易见。优点是无视两个类的位置、无需同名同结构,缺点是有额外工作(写接口)外加反序列化后只能得到接口不能得到classB。额外注意,上例中使用的二进制序列化需要在类上标记[Serializable]。

 

 

除此之外还有很多种方法可以做跨域类型转换,但并不常用,这里就不再敖述了。

转载于:https://www.cnblogs.com/yy1234/p/8405556.html

更多相关:

  • 一、自定义序列化组件 新建一个任意名的py文件,里面导入serlizerfrom rest_framework import serializers 自定义一个类继承serializers,里面写需要序列化的字段方法一:继承serializers.Serializerclass BookSerlizer(serializers.S...

  • import pickle d = {   'name':'alex',   'role':'police',   'blood': 76,   'weapon':'AK47' } d_dump = pickle.dumps(d) #序列化 print (pickle.loads(d_dump)) #反序列化 f = open('ga...

  •   一年前就已经用过restframework, 当时觉得这个只是给web框架打辅助的, 他能实现的我也都实现(可能没有那么好用, 嘿嘿) 但是我有一种东西叫做效率, 时间就是金钱, 别人造好的就直接用就可以了, 自己其实没必要在去重复.   最近写一个调查问卷系统, 利用了以下知识点   1. django   2. restfra...

  • 原文出自:http://www.importnew.com/21517.html 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类...

  • 菜鸟一枚,正在学习C++ Gui Qt4,整理很零碎,欢迎批评指正   1.窗口标题: QWidget *window = new QWidget; window->setWindowTitle("Enter Your Age"); **************************************** 关于标题...

  • 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入:1->2->4, 1->3->4 输出:1->1->2->3->4->4 总体思路是: 比较两个链表头节点,较小的插入新链表指针之后,同时较小链表指针向后移动一位 实现如下: ListNode* mergeTwo...

  • 1.直接调用微软socket对象处理 static void Main(string[] args){try{IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });//在3721端口新建一个TcpListener对象TcpListener listener = new...

  •   现在很多地方都会用到zookeeper, 用到它的地方就是为了实现分布式。用到的场景就是服务注册,比如一个集群服务器,需要知道哪些服务器在线,哪些服务器不在线。   ZK有一个功能,就是创建临时节点,当机器启动应用的时候就会连接到一个ZK节点,然后创建一个临时节点,那么通过获取监听该路径,并且获取该路径下的节点数量就知道有哪些服务...

  • 前台到后台java时data日期类型的转化 在实体类中用@DataTimeFormat,这样设置即使传过来是空的字符串也是可以转的,要和前面传过来的格式一致,如 @XmlElement(name="BeginDate") @DateTimeFormat(pattern="yyyy-MM-dd") private Date begin...