之前研究过自定义对象的socket传输,当时认识太浅了,实在是无法理解,现在重新研究了一次,调试通过,仅作为记录笔记。
C#中,目前我所知道的序列化与反序列化有两种,当然有更多,但是我还没有去认识。
这两种序列化方式分为:
- System.Runtime.Serialization.Formatters.Binary空间下的BinaryFormatter。
- System.Runtime.Serialization空间下的DataContractSerializer。
第一种序列化就我目前认知来看,不能作为不同工程之前的序列化操作,也就是说不同命名空间下的程序序列化出来的信息不能共享,我尝试着在一个工程中序列化数据,然后使用socket传输给第二个工程来反序列化,结果报错,报错的大致意思就是说我序列化的内容在我反序列化的时候不能找到精确的类型来匹配,想想也是,序列化和反序列化实在两个不同的工程中,命名空间和类的定义都不一样,反正没有深究。
第二种序列化不用担心这个问题,因为DataContractSerializer在初始化的时候必须要传递一个参数来实现构造,这个参数就是我将做的序列化操作对应的类的类型是什么,这样的话,我根本就不用担心类型匹配的问题。但是有一点要注意的是,DataContractSerializer没有在默认的这个空间中,需要引用System.Runtime.Serialization.dll才可以使用这个函数。
第一种方式的序列化和反序列化:
- public Stream serializeStream_sameProject(object param)
- {
- BinaryFormatter formmatter = new BinaryFormatter();
- MemoryStream stream = new MemoryStream();
- formmatter.Serialize(stream, param);
- return stream;
- }
- public object deserializeStream_sameProject(Stream stream)
- {
- BinaryFormatter formatter = new BinaryFormatter();
- stream.Seek(0, SeekOrigin.Begin);
- object obj = formatter.Deserialize(stream);
- return obj;
- }
第二种方式的序列化和反序列化:
- public Stream serializeStream(object param)
- {
- DataContractSerializer serializer = new DataContractSerializer(param.GetType());
- MemoryStream stream = new MemoryStream();
- serializer.WriteObject(stream, param);
- return stream;
- }
- public object deserializeStream(Stream stream,Type paramType)
- {
- DataContractSerializer serializer = new DataContractSerializer(paramType);
- stream.Seek(0, SeekOrigin.Begin);
- object obj = serializer.ReadObject(stream);
- return obj;
- }
关于socket传输对象的办法,使用第二种序列化,将对象转换为byte数组,使用socket传输过去。
接收方接收到数组之后,又将数组反序列化回对象。
传输过程中的对象必须传输方和接收方都可以识别。
序列化的类必须以[Serializable]标明。
最近无聊在写个传输的东西,发现个问题,现在补充一下,2012-01-30
如果传输的对象的类型中有其他的类型,而这些类型并没有被申明的话,那么在执行WriteObject的时候会报错,因为编译器认为类型不明确或者不认识。
这个时候需要为序列化的类型进行类型申明。
- [DataContract]
- [KnownType(typeof(Bitmap))]
- public class ImageData : ContractData
- {
- [DataMember]
- public string imageName { get; set; }
- [DataMember]
- public Image image { get; set; }
- [DataMember]
- public int index { get; set; }
- }
- 例如上面这个类型,Image类型虽然是类库中的类型,但是WriteObject仍然会报错,因为这个类型没有被申明。
- 需要使用DataContract、KnownType、DataMember来标明。
- DataMember是必须要的,否则WriteObject根本不会序列化,传过去也是个空的。