2013-04-29 3 views
2

protobuf-net 라이브러리를 사용하여 개체 컬렉션을 serialize하려고합니다. 나는 컬렉션의 최상위 오브젝트가 그래프의 참조로 설정되지 않는 문제에 직면 해있다. 그래서 직렬화 된 하위에서 더 아래로 참조 될 때, 그들은 다시 직렬화되고 그 시점에서 참조로 작성된다. . 상위 수준 개체를 참조로 serialize 할 수있는 방법이 있습니까? protobuf-net이 이제 이것을 지원함을 나타내는 여러 충돌하는 게시물을 읽었으며, 다른 게시물은이 동작을 가능하게하기 위해 최상위 레벨 객체 주위에 래퍼를 만드는 것이 좋습니다. 감사합니다 ...Protobuf-net 루트 수준 목록 Serialization AsReference

여기 내 문제를 보여주는 샘플 프로그램입니다. 보시다시피, 참고 문헌은 동일하지 않습니다.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using ProtoBuf; 

namespace ProtoBufTest 
{ 
    [ProtoContract(AsReferenceDefault=true)] 
    public class Foo 
    { 
     [ProtoMember(1, AsReference=true)] 
     public FooChild Child; 

     [ProtoMember(2)] 
     public Guid Id; 
    } 

    [ProtoContract] 
    public class FooChild 
    { 
     [ProtoMember(1, AsReference=true)] 
     public Foo Parent; 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Foo> foos = new List<Foo>() 
      { 
       new Foo() { Child = new FooChild(), Id = Guid.NewGuid() } 
      }; 

      foos[0].Child.Parent = foos[0]; 

      var clone = Serializer.DeepClone(foos); 

      Console.WriteLine(ReferenceEquals(clone[0], clone[0].Child.Parent)); 
      Console.WriteLine(clone[0].Id == clone[0].Child.Parent.Id); 
     } 
    } 
} 

답변

0

실제로 의미하는 경우 루트 개체 (즉 Serialize에 전달 된 객체), 그 간단하게 예를 들어, 작동합니다 : 그것은 작동하지

using ProtoBuf; 
using System; 
[ProtoContract] 
public class Foo 
{ 
    [ProtoMember(1)] 
    public Bar Bar { get; set; } 
} 
[ProtoContract] 
public class Bar 
{ 
    [ProtoMember(1, AsReference = true)] 
    public Foo Foo { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     var foo = new Foo { Bar = new Bar() }; 
     foo.Bar.Foo = foo; 
     var clone = Serializer.DeepClone(foo); 

     // writes: True 
     Console.WriteLine(ReferenceEquals(clone, clone.Bar.Foo)); 
    } 
} 

경우 , 그렇다면 실제로는 루트이 아닌 것으로 의심됩니다. 그러나 그래프에서 (루트가 아닌) 높은 것입니다.이 경우 AsReference=true을 추가하면 문제를 해결할 수 있습니다.

나는 또한 일반 공개 기한을 넘겼지만 소스 코드는 이제 다음 빌드에 포함될 계약 레벨에서이를 표현할 수있는 훨씬 더 나은 지원을 제공합니다. 예를 들어, (여기에 메모리에서 작업) :

[ProtoContract(AsReferenceDefault=true)] 
public class Foo 
{ 
    [ProtoMember(1)] 
    public Bar Bar { get; set; } 
} 

이를 암시 적 상관 Foo 회원 참조 명시 적으로 비활성화됩니다하지 않는 (AsReference=false)로서 직렬화되어야한다고 가정합니다.

+0

빠른 응답을 보내 주셔서 감사합니다. btw, 귀하의 도서관은 우리의 응용 프로그램에 아주 좋았으며이 몇 가지 예외를 제외하고 모든 WCF 서비스를 위해 노력하고 있습니다. 내가 그것을 잘 물어 보지 않았다는 것을 알았을 때 나는 내 질문을 조금 분명히 해 줄 것이다. 직렬화하려고하는 루트 객체는 IList입니다. - Foo는 AsReferenceDefault = true ProtoContract 속성으로 표시되지만 목록의 Foo 객체는 참조로 처리되지 않습니다. – Nick

+0

@ user1863798 내가 재현하기 위해 사용할 수있는 짧지 만 완전한 예를 제시 할 수 있습니까? (한 번 조정하면 작업이 계속 수행되도록하기위한 통합 테스트로 사용) –

+0

추가 된 샘플 코드를 알리는 태그를 추가하기 만하면됩니다. – Nick