2014-01-06 3 views
0

다음 코드에는 2 개의 정적 상태 (초기 상태 및 마지막 상태)가 있습니다. Test 클래스가 처음 생성되면 InitialStatus라는 상태로 생성됩니다. 이 상태는 별도의 호출 (ChangeStatus)을 통해 변경 될 수 있습니다.Protobuf-Net은 새 객체를 생성하고 할당하는 대신 기존 객체를 재사용하는 것 같습니다.

TestClass의 개체를 만들고 상태를 변경 한 다음 해당 개체를 직렬화 및 비 직렬화하면 InitialStatus의 값을 덮어 쓰는 것처럼 보입니다. 따라서 본질적으로 Protobuf는 데이터를 비 직렬화 할 때 사용할 수있는 기존 객체를 재사용하는 것으로 보입니다. (그러나 객체가 null 인 경우에는 그렇게하지 않습니다.) deserialization 후 객체가 기존 변수를 재사용하는 대신 재구성 될 수 있도록이 동작을 사용자 정의 할 수있는 방법이 있습니까?

[ProtoContract] 
public class Status 
{ 
    private static Status _initialStatus; 
    public static Status InitialStatus 
    { 
     get{ 
      if (_initialStatus == null) 
      { 
       _initialStatus = new Status{StatusId=-1}; 
      } 
      return _initialStatus; 
     } 
    } 

    private static Status _lastStatus; 
    public static Status LastStatus 
    { 
     get{ 
      if (_lastStatus == null) 
      { 
       _lastStatus = new Status{StatusId=-2}; 
      } 
      return _lastStatus; 
     } 
    } 

    [ProtoMember(101)] 
    public int StatusId{get; private set;} 
} 

[ProtoContract] 
public class TestClass2 
{ 
    public TestClass2() 
    { 
     Initialize(); 
    } 

    private void Initialize() 
    { 
     CurrentStatus = Status.InitialStatus; 
    } 

    [ProtoMember(101)] 
    public Status CurrentStatus{get; private set;} 

    public void ChangeStatus(Status newStatus) 
    { 
     CurrentStatus = newStatus; 
    } 
} 


void Main() 
{ 
    TestClass2 test = new TestClass2(); 

    test.ChangeStatus(Status.LastStatus); 


    string serializedTest = ProtoUtils.Serialize(test); 
    TestClass2 testDeserialized = ProtoUtils.Deserialize<TestClass2>(serializedTest); 

    Debug.Assert(Status.InitialStatus.StatusId == -1, "Initial Status has changed"); 
    Debug.Assert(Status.LastStatus.StatusId == -2, "Last Status has changed"); 
} 


public static class ProtoUtils 
{ 
    public static string Serialize(Object o) 
    { 
     String result = String.Empty; 

     using (MemoryStream stream = new MemoryStream()) 
     { 
      Serializer.Serialize(stream, o); 

      result = Convert.ToBase64String(stream.ToArray()); 
     } 
     result.Dump(); 
     return result; 
    } 

    public static T Deserialize<T>(string data) 
    { 
     T result = default(T); 

     if (data != null) 
     { 
      byte[] dataBytes = Convert.FromBase64String(data); 

      using (Stream stream = new MemoryStream(dataBytes)) 
      { 
       result = Serializer.Deserialize<T>(stream); 
      } 

     } 

     return result; 
    } 
} 
+0

안녕하세요, ProtoUtils 코드를 제공 할 수 있습니까? 끝까지 테스트 해봐. –

답변

1

옵션 :

  • ProtoContractAttribute에 SkipConstructor를 지정 -이 객체 생성시 초기화되는 필드를 방지 할 수
  • 사용 사전이 직렬화 콜백 (해당 속성으로 장식 된 인스턴스 메서드) 그리고 필드를 지우십시오 - 이것은 건설 후 데이터가 읽히기 전에 발생합니다.
+0

이 질문에 지정해야합니다 있지만 건너 뛸 생성자 건너 뛸. 주로 실제 코드에서는 생성자가 건너 뛸 수없는 추가 작업을 수행하기 때문입니다. 콜백을 사용하지 않기를 바랬습니다. –

+0

@RajRao 개인적으로 나는 여전히 필요한 코드를 실행하기 위해 건너 뛰는 생성자와 콜백의 조합을 사용합니다. 대신 사용자 정의 팩토리는 어떻습니까? 제가 언급하지 않은 세 번째 옵션은 protobuf-net에 정적 메소드를 사용하여 인스턴스를 생성 할 수 있다는 것입니다. 그러면 인스턴스를 원하는대로 초기화 할 수 있습니다 –