2009-04-23 24 views
8

Tôi đã sử dụng để sắp xếp một số lần xem trang với BinaryFormatter (C#). Hội đã làm điều đó và có chứa tất cả các lớp serializable bây giờ có một tên mạnh mẽ và được ký kết và cũng có một số phiên bản mới (tuy nhiên, thực hiện không thay đổi).Deserialize đối tượng vào lắp ráp mà bây giờ đã được ký và được phiên bản

Khi tôi cố gắng deserialize byte [] array, dòng

(TreeViewData)binaryFormatter.Deserialize(memoryStream); 

tạo ra một ArgumentNullException. (Tên người dùng: loại)

Tôi nghĩ rằng versionnumber là vấn đề, vì vậy tôi đã triển khai một Binder riêng. Tôi ghi đè phương thức BindToType và đảm bảo rằng phiên bản đã được sửa và loại trả về đúng.

Tuy nhiên, tại thời điểm đó, chương trình rời khỏi phương thức BindToType, tôi vẫn nhận được ngoại lệ được đề cập ở trên.

Làm cách nào để khắc phục sự cố này?

Trả lời

3

Bạn có thể thử sử dụng một đại diện tuần tự, nhưng không có một cái gì đó chúng ta có thể tái tạo nó sẽ khó có thể đưa ra một câu trả lời nha.

Vấn đề cơ bản, tuy nhiên, BinaryFormatter đơn giản là rất, rất giòn khi nói đến những thứ như hội đồng. Heck, nó đủ giòn thậm chí within an assembly.

Nghe có vẻ như TreeViewData là dựa trên cây, vì vậy tôi tự hỏi liệu xml có phải là tùy chọn tốt hơn (tức là phiên bản khoan dung hơn) hay không. Nếu hiệu quả là một mối quan tâm, có các định dạng nhị phân tùy chỉnh (như protobuf-net) cung cấp hiệu suất cao, phiên bản khoan dung, tuần tự nhị phân di động. Nếu dữ liệu của bạn đã được tuần tự hóa ... Tôi tự hỏi nếu có thể là thời gian để thay đổi bản nhạc? Hãy thử sử dụng lắp ráp cũ để deserialize dữ liệu, và chuyển sang một chiến lược serialization mạnh mẽ hơn.

11

Bạn có thể sử dụng một SerializationBinder để giải quyết này:

private class WeakToStrongNameUpgradeBinder : SerializationBinder 
{ 
    public override Type BindToType(string assemblyName, string typeName) 
    { 
     try 
     { 
      //Get the name of the assembly, ignoring versions and public keys. 
      string shortAssemblyName = assemblyName.Split(',')[0]; 
      var assembly = Assembly.Load(shortAssemblyName); 
      var type = assembly.GetType(typeName); 
      return type; 
     } 
     catch (Exception) 
     { 
      //Revert to default binding behaviour. 
      return null; 
     } 
    } 
} 

Sau đó

var formatter = new BinaryFormatter(); 
formatter.Binder = new WeakToStrongNameUpgradeBinder(); 

Voila, các đối tượng serialized cũ của bạn có thể được deserialized với định dạng này. Nếu loại cũng đã thay đổi, bạn có thể sử dụng một số SerializationSurrogate để loại bỏ các loại cũ thành các loại mới của bạn.

Như những người khác đã đề cập, thực hiện tuần tự hóa của riêng bạn thay vì dựa vào IFormatter là một ý tưởng tốt vì bạn có nhiều quyền kiểm soát hơn đối với phiên bản và kích thước được tuần tự hóa.

+0

Oh cảm ơn bạn rất nhiều. –

1

Đề xuất của tôi là không bao giờ sử dụng serialized nội tuyến cho lưu trữ liên tục của bạn. Luôn tự viết mã nếu không có lý do nào khác vào một ngày nào đó trong tương lai, bạn sẽ cần phải đọc và ghi các định dạng tệp của mình từ một ngôn ngữ khác.

Các vấn đề liên quan