2016-11-08 4 views
1

실습을 위해 serializer (C#)를 구현하려는 경우 순환 식 참조에서 해당 serializer가 실패하지 않도록하는 것이 좋습니다.순환 참조를 사용하여 개체 그래프 직렬화 방법 접근 방식

아직 해결되지 않은 개체를 직렬화하고 존재하지 않는 개체는 건너 뛸 수 있습니다. 이는 인스턴스를 해싱 (hash)하여 쉽게 수행 할 수 있습니다.

제안 된 솔루션은 "개체의 ID를 정의하는 것은 무엇입니까?"라는 질문을 제안합니다. GetHashCode 및 Equals 메서드를 사용합니다. 이것은 직렬화시 시간을 절약하고 비 직렬화시 메모리를 보존하는 수용 가능한 솔루션입니다.

그러나 많은 인스턴스가 동일한 ID를 가지고 있지만 아직 직렬화 된 도메인에서 완전히 다른 것들에 사용될 수 있으므로 나중에 동일한 인스턴스가 도메인 논리를 위반하게 될 수 있으므로 항상 바람직한 결과는 아닙니다. .

그런 serializer의 저자로서, 나는 그러한 결정을 내리기 위해 호출자에게 맡겨야한다.

이 문제를 해결하기위한 한 가지 방법은 컬렉션을 반복하고 각 포함 된 요소에서 ReferenceEquals를 호출하여 직렬화 된 인스턴스와 직렬화되지 않은 인스턴스를 구별하는 것입니다. 이 방법이 효과적이지만 성능은 현저히 낮습니다.

또 다른 접근법은 관리되지 않는 힙에 개체를 고정하고 고정 된 개체 주소를 ID로 사용하는 것입니다.이 개체는 과도한 잔인 함으로 보이며 많은 오버 헤드가 있습니다.

또 다른 접근법은 리플렉션을 사용하여 모든 인스턴스의 Object.Equals 및 Object.GetHashCode 기본 구현을 호출하는 것인데, 이는 문제를 해결하는 것으로 보이지만 약간의 오버 헤드가 있습니다.

내 질문은 : 내가 제시 한 방법에 놓친 어떤주의 사항이

1)이 있습니까?
2) 생각지도 못했던 추가 접근법이 있습니까?

답변

1

System.Runtime.Serialization.ObjectIDGenerator을 살펴보십시오. 그것은 정확하게 그것을합니다.페이지는 MSDN에 따르면

: 해시 테이블을 사용

는 ObjectIDGenerator는 ID가 어떤 오브젝트에 할당되는 유지한다. 각 오브젝트를 고유하게 식별하는 오브젝트 참조는 런타임 가비지 수집 힙의 주소입니다. 오브젝트 참조 값은 직렬화 중에 변경 될 수 있지만 테이블은 정보가 올 Y 르게 자동으로 갱신됩니다.

소스 코드도 사용할 수 있습니다. here.

0

순환 참조를 실제로 일으키는 유일한 것 (예 : 앱의 네버 앤드 루프)은 실제 객체 참조입니다. 따라서 해시 목록을 유지하지 않고 이전에 발생 된 개체의 목록을 유지하십시오.

직렬화 된 데이터를 가능한 한 작게 유지하려면 nuget이 패키지 폴더를 구성하는 것과 비슷한 방법으로 구현할 수 있습니다. 각 객체를 한 번만 쓰고 하나의 객체가 다른 객체를 참조하는 경우 일종의 참조 키를 작성하십시오 .

[ 
    { 
     serialisationKey: "GUID1", 
     name: "Neil", 
     friends: [ 
      { obj: "GUID2" }, 
      { obj: "GUID3" } 
     ] 
    }, 
    { 
     serialisationKey: "GUID2", 
     name: "Bob", 
     friends: [ 
      { obj: "GUID1" } 
     ] 
    }, 
    { 
     serialisationKey: "GUID3", 
     name: "Alf", 
     friends: [ 
      { obj: "GUID1" } 
     ] 
    } 
] 
+0

제안 된 첫 번째 방법을 사용하는 것이 좋습니다. 나는 당신의 의견을 소중하게 생각하지만 내 두 가지 질문에 답하지 않습니다. 또는 나는 무엇인가 놓치고 있냐? –

0

메모리에 고정하지 마십시오! object.ReferenceEquals

serializer가 똑똑하지 않아야하며 같은 개체를 하나의 개체 또는 두 개의 개체로 serialize해야하는지 확인해야합니다. 각 객체를 한 번 직렬화합니다. 객체가 두 번 참조되는 경우 직렬화 된 데이터에서 두 번 참조하십시오.

+0

제안 된 첫 번째 방법을 사용하는 것이 좋습니다. 나는 당신의 의견을 소중하게 생각하지만 내 두 가지 질문에 답하지 않습니다. 또는 나는 무엇인가 놓치고 있냐? –