4

이진 직렬화를 사용하여 .NET 2.0 Remoting을 통해 통신하는 클라이언트 및 서버 응용 프로그램이 있습니다.이진 직렬화, 클래스에 새 필드 추가 - 작동합니까?

데이터 전송 개체의 인터페이스와 구현 클래스 중 하나에 약간의 변경이있었습니다. 문자열 배열이 추가되었습니다.

새 버전의 서버 응용 프로그램을 재배포하려면 기존 클라이언트가 계속 작동합니까?

인터페이스 및 직접 구현에서 아무 것도 삭제되지 않았으므로 나는 생각할 것입니다. 그러나 확실하지 않습니다.

아마도 다른 질문으로 귀결 될 것입니다. 이진 직렬화 기는 에 이진 입력기 이진 스트림에서 데이터를 찾지 못하는 필드를 초기화하여이 상황을 처리하거나 "깨뜨릴 것"입니다. 그리고 예외를 던지기 위해서?

답변

4

새 속성에 속성을 추가 할 수 있습니다 : OptionalField. 특성이 없으면 디시리얼라이저는 직렬화 된 데이터를 업데이트 된 정의로 다시 변환 할 수 없습니다. 이 속성은 디시리얼라이저가 누락 된 데이터를 정상적으로 처리 할 수 ​​있는지 확인하는 것입니다.

새 속성의 기본값을 설정하려는 경우 적절한 데이터가 deserialize되지 않은 경우 IDeserializationCallback 인터페이스를 구현하고 결과 메서드에서 기본값을 설정합니다 (있는 경우).

0

의 고유 한 메서드를 사용하여 버전 관리를 구현하면 ISerializable에서 상속하여 사용자 고유의 serializer를 구현하고 예외를 throw 할 수 있습니다.

public bool Deserialize(string sFileName) { 
      bool bSuccessful = false; 
      // 
      if (!System.IO.File.Exists(sFileName)) return false; 
      fuBar = new MyFooBar(); 
      // 
      try { 
       using (FileStream fStream = new FileStream(sFileName, FileMode.Open)) { 
        try { 
         BinaryFormatter bf = new BinaryFormatter(); 
         fuBar = (MyFooBar)bf.Deserialize(fStream); 
         bSuccessful = true; 
        } catch (System.Runtime.Serialization.SerializationException sEx) { 
System.Diagnostics.Debug.WriteLine(string.Format("SERIALIZATION EXCEPTION> DETAILS ARE {0}", sEx.ToString())); 
         bSuccessful = false; 
        } 
       } 
      } catch (System.IO.IOException ioEx) { 
       System.Diagnostics.Debug.WriteLine(string.Format("IO EXCEPTION> DETAILS ARE {0}", ioEx.ToString())); 
       bSuccessful = false; 
      } 
      return (bSuccessful == true); 
     } 

아래와 같이 데이터가 2.0 이상에서이 작업을 수행 할 수있는 더 깔끔한 방법이 여기에 예를 들어

using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 

public class MyFooBar : ISerializable{ 
    private float _fVersion = 1.0; 
    public MyFooBar(SerializationInfo info, StreamingContext context) { 
     this._fVersion = info.GetSingle("FooBarVersionID"); 
     if (this._fVersion == 1.0F) bOk = this.HandleVersionOnePtZero(info, context); 
     if (!bOk) throw new SerializationException(string.Format("MyFooBar: Could not handle this version {0}.", this._fVersion.ToString())); 
    } 
    [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)] 
    public void GetObjectData(SerializationInfo info, StreamingContext context) { 
     info.AddValue("FooBarVersionID", this._fVersion); 
     if (this._fVersion == 1.0F) { 
      // Bool's... 
      info.AddValue("FooBarBool", FooBarBool); 
      // etc... for Version 1.0 
     } 
     if (this._fVersion == 1.1F){ 
      // etc... for Version 1.0 
     } 
    } 
} 

그리고/역 직렬화를 직렬화 할 때이 상황에서 MyFooBar를 사용의 ... 직렬화 쪽으로 와드,하지만 나는이 방법을 선호한다.

관련 문제