解決反序列化(Deserialize)無法找到程序集的錯誤

在使用.NET序列化對象時,會將程序集信息也包含進去。如果將序列化之後的字節數組通過網絡(或其他傳輸方式)傳輸到另一個應用程序,再使用Deserialize反序列化還原對象時,可能(注意是可能)會出現無法找到程序集的錯誤。之所以說是可能,是因爲如果兩邊的應用程序結構(命名空間、類結構、程序名、程序簽名、程序版本等)相同,則不會出現該錯誤。下面說一個具體實例:

在客戶端動態生成一條SELECT語句,將該語句發送到服務器執行,再將執行後的結果返回給客戶端。(題外話:要實現本功能完全可以不使用序列化和反序列化的方法,本實例只是爲了解釋如何解決反序列化時出現的無法找到程序集的錯誤)

解決方案:

創建一個.NET類庫,把要傳輸的對象做成一個結構或類放在類庫(假設爲ClassLib.dll)中。如:

view plaincopy to clipboardprint?
[Serializable]  
public struct Data  
{  
    public string sql;  

[Serializable]
public struct Data
{
    public string sql;
}

 

然後在客戶端程序(假設爲Client.exe)中引用ClassLib.dll,創建Data對象,給Data.sql賦值,再調用Serialize方法將Data對象序列化成字節數組發送出去。參考代碼:

 view plaincopy to clipboardprint?
BinaryFormatter formatter = new BinaryFormatter();  
MemoryStream mem = new MemoryStream();  
 
ClassLib.Data data;  
data.sql="select * from table";  
formatter.Serialize(mem, data);  
mem.Seek(0, SeekOrigin.Begin);  
byte[] buffer = mem.GetBuffer(); //這裏使用mem.GetBuffer()要比mem.ToArray()效率高,  
                                   //因爲前者直接返回mem使用的內存,後者是創建一塊合適大小的內存,  
                                    //再將mem對象緩存中的數據拷貝進去。  
                                    //但是如果改變使用GetBuffer方法返回的數組中數據的值,  
                                    //則mem對象緩存中的值也會變化  
Send(buffer, mem.Length); //Send原型爲 void Send(byte[] buf, long bufLen)  
                          //之所以Send函數要有第2個參數bufLen,  
                             //是因爲使用GetBuffer方法返回的緩存中有未使用的字節  
                             //通過給該參數傳遞mem.Length可以讓Send函數只發送使用的字節 
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream mem = new MemoryStream();

ClassLib.Data data;
data.sql="select * from table";
formatter.Serialize(mem, data);
mem.Seek(0, SeekOrigin.Begin);
byte[] buffer = mem.GetBuffer(); //這裏使用mem.GetBuffer()要比mem.ToArray()效率高,
                                   //因爲前者直接返回mem使用的內存,後者是創建一塊合適大小的內存,
                                    //再將mem對象緩存中的數據拷貝進去。
                                    //但是如果改變使用GetBuffer方法返回的數組中數據的值,
                                    //則mem對象緩存中的值也會變化
Send(buffer, mem.Length); //Send原型爲 void Send(byte[] buf, long bufLen)
                          //之所以Send函數要有第2個參數bufLen,
                             //是因爲使用GetBuffer方法返回的緩存中有未使用的字節
                             //通過給該參數傳遞mem.Length可以讓Send函數只發送使用的字節

在服務器端(假設爲Server.exe)中也引用ClassLib.dll,調用Deserialize函數反序列化接收到的字節得到Data對象。參考代碼:

view plaincopy to clipboardprint?
ClassLib.Data data = (ClassLib.Data)formatter.Deserialize(new MemoryStream(data, index, length)); 
ClassLib.Data data = (ClassLib.Data)formatter.Deserialize(new MemoryStream(data, index, length));

至此序列化和反序列化完成。今後在庫變換時,只要保證服務器和客戶端的庫一致,就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章