2012-04-19 17 views
6

Tôi có lớp nàyChiến lược deserializing một lớp học mà đã thay đổi trong .NET

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public int b; 
    public int c; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

Tôi có hàng trăm những đối tượng trong cơ sở dữ liệu của tôi. Tôi bây giờ đã sẵn sàng để xuất bản một phiên bản mới của ứng dụng của tôi, nơi lớp đã morphed để

[Serializable] 
public class myClass() : ISerializable 
{ 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
           StreamingContext context) 
     { 
     // Some code 
     } 

    public myClass(SerializationInfo info, 
        StreamingContext context) 
     { 
     // Some code 
     } 
} 

Làm thế nào người ta sẽ deserialize một đối tượng đăng dựa trên phiên bản đầu tiên với các nhà xây dựng de-serialization của thứ hai.

Có các chiến lược cho phiên bản tương lai kiểm chứng phiên bản thứ hai của lớp không?

+1

Thực hiện một chương trình chuyển đổi mà đọc đối tượng của kiểu đầu tiên, tạo ra các đối tượng của kiểu thứ hai và thay thế các đối tượng cũ bằng mới. Chạy chương trình đó sẽ mất nhiều thời gian, nếu bạn đang nói về hàng trăm, không phải hàng triệu hồ sơ. – dasblinkenlight

+2

Có một bài viết chuyên về MSDN về nó. Bắt đầu tốt hơn ở đó: http://msdn.microsoft.com/en-US/library/ms229752%28v=vs.90%29.aspx –

Trả lời

4

Nếu không có sự chuẩn bị từ phía bạn, bạn có thể cần phải dùng đến một hack: khi public myClass deserialization constructor của bạn được giá trị của bool d, kèm theo mã trong try/catch, và thiết lập d để giá trị mặc định của nó khi bạn bắt một ngoại lệ .

Trong tương lai, thêm một int giá trị "__ver" (hoặc bất kỳ tên khác mà không va chạm với lập luận rằng bạn vượt qua để info.AddValue), và đặt nó là một hằng số mà bạn duy trì trong lớp học của bạn để chỉ ra những thay đổi tương thích và không tương thích trong serialization:

public class myClass : ISerializable { 
    private const int __ver = 4; 
    public int a; 
    public string b; 
    public int c; 
    public bool d; 

    public void GetObjectData(SerializationInfo info, 
          StreamingContext context) { 
     info.AddValue("__ver", ver); 
     info.AddValue("a", a); 
     // and so on 
    } 

    public myClass(SerializationInfo info, 
       StreamingContext context) { 
     switch(info.GetInt32("__ver")) { 
      case 3: 
       // Deserialize prior version 
      break; 
      case 4: 
       // Deserialize current version 
      break; 
     } 
    } 
} 
+0

Chỉ có vấn đề là tất cả các cá thể hiện tại trong cơ sở dữ liệu không có trường __ver trên chúng , vì vậy bạn sẽ không thể trang bị thêm việc triển khai này. –

+0

'SerializationInfo' không có một cái gì đó như' ContainsKey() '? Tôi nghĩ điều đó rất hữu ích ở đây. – svick

+0

Tôi nghĩ bạn có thể sử dụng 'MemberCount' hoặc' GetEnumerator() 'để tránh' try'/'catch'. – svick

2

Các lớp có thể lập trình rất tuyệt vời để chuyển chúng qua cùng một phiên bản phần mềm, nhưng bạn nhấn nhanh vấn đề này khi sử dụng nó. Nếu bạn định lưu trữ các đối tượng là BLOBs, thì có thể sử dụng một cái gì đó như protobuf-net cho phép phiên bản tuần tự hóa bằng cách cho phép các trường tùy chọn.

Với tình cảnh hiện tại của bạn tất cả các bạn có thể làm để làm cho nó hoạt imediatly là đặt một catch xung quanh các lĩnh vực mới, và sau đó mặc họ nếu họ không có:

protected myClass(SerializationInfo info, StreamingContext context) 
{ 
    c = info.GetInt32("Value_C"); 
    try 
    { 
     b = info.GetBoolean("Value_B"); 
    } 
    catch (SerializationException) 
    { 
     b = true; 
    } 
} 
Các vấn đề liên quan