代码改变世界

基本.NET深串行化

2008-08-12 00:28  Kevin-wang  阅读(324)  评论(0编辑  收藏  举报
深串行化:串行化对象的整个状态
    使用命名空间:
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;

    串行化类的标志:在类前加上[Serializable]特性
    两种格式器:BinaryFormatter,SoapFormatter

    以BinaryFormatter为例(SoapFormatter与之相同)
    串行化模板:

        public void SerializeIt(string filename)
        
{
            Book myBook 
= new Book();

            BinaryFormatter formatter 
= new BinaryFormatter();
            FileStream fs 
= File.Create(filename);
            formatter.Serialize(fs, myBook);
            fs.Close();
        }

    反串行化模板:

        public void DeserializeIt(string filename)
        
{
            BinaryFormatter formatter 
= new BinaryFormatter();
            FileStream fs 
= File.OpenRead(filename);
            Book myBook 
= (Book)formatter.Deserialize(fs);
            fs.Close();
        }

*在字段上加上[NonSerialized],可以不使该字段被序列化
*对于引用关系,如果A中引用了B,A和B类都要加上[Serializable],才能对A进行串行化
*对于循环引用,只支持对象图的循环引用,不支持广义的对象循环引用
    对象图循环引用的例子:

    [Serializable]
    
public class Book
    
{
        
private BookCatalog includeInBookCatalog;

        
public BookCatalog IncludeInBookCatalog
        
{
            
get return includeInBookCatalog; }
            
set { includeInBookCatalog = value; }
        }

    }


    [Serializable]
    
public class BookCatalog
    
{
        
private Book[] books;

        
public Book[] Books
        
{
            
get return books; }
            
set 
            

                books 
= value;

                
foreach (Book book in books)
                
{
                    book.IncludeInBookCatalog 
= this;
                }

            }

        }

    }

BookCatalog进行深度序列化,不会造成循环引用,因为格式化器Formatter知道无论对象有多少个引用,保证每个对象只串行化一次——通过System.Runtime.Serialization下的两个类实现:ObjectManagerObjectIDGenerator
    ObjectManager        负责在对象反串行化时跟踪对象,确定该对象是否串行化过
    ObjectIDGenerator  为每个被跟踪的对象加一个唯一的ID以区别,根据对象是否被串行化,ObjectIDGenerator知道是返回已有的ID,还是生成一个新的ID
格式化器不会提前检查所有的对象可串行化,中途如果发生异常,可以已经生成部分对象了。

通过深串行化克隆对象:
    先串行化,在内存流上使用二进制深度复制;然后再找到流的开头,进行反串行化

        public object Clone(object source)
        
{
            MemoryStream stream 
= new MemoryStream();
            BinaryFormatter formatter 
= new BinaryFormatter();
            formatter.Context 
= new StreamingContext(StreamingContextStates.Clone);
            formatter.Serialize(stream, source);
            stream.Position 
= 0;
            
return formatter.Deserialize(stream);
        }