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

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

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

 

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

 

  解决此问题的方法很多,但都逃不开一个关键思想: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:\tmp.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:\tmp.txt" , System.IO.FileMode.Open, System.IO.FileAccess.Read));

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

1
2
3
4
5
<?xml version= "1.0" ?>
<classA xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd= "http://www.w3.org/2001/XMLSchema" >
   <i>10</i>
   <s>hello</s>
</classA>

这表明了传输的内容只关注类名和共有属性/字段。所以在反序列化端,只要我们有同样结构的同名类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:\tmp" , 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:\tmp" , System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Read));

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

 

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值