2017-03-28 1 views
1

protobuf를 사용하여 어떤 유형이 de/serialize되어 있는지 런타임에서 알 수 없을 때 가장 좋은 방법은 무엇입니까?많은 알 수없는 유형의 Protobuf

현재 직렬화에 적합한 후보가되는 유형의 형식 초기화 프로그램에서 RuntimeTypeModel을 확장하는 아이디어를 가지고 있습니다. 그러나 다른 프로세스에서 비 직렬화 할 때 유형을 직렬화하는 데 사용 된 동일한 유형의 모델을로드해야합니다. 직렬화 된 데이터를 디스크에서 다시 읽을 때 나중에 다시 사용하기 위해 RuntimeTypeModel을 디스크로 직렬화 할 수 있습니까? 이상적으로는 모델을 직렬화 된 스트림에 넣고 완전한 자체 기술 객체 모델을 가질 수 있습니다. 또는 단계를 기록하고이 데이터를 직렬화 된 스트림 앞에 넣어야합니까?

실제 데이터와 런타임 유형 모델 및 꽤 좋은 길이에 대한 오프셋을 포함하는 헤더를 만들 수 있습니다. 또는 직렬화 시간에 모든 유형의 등록 된 아키텍처에서 플러그를 다루는 더 나은 방법이 있습니까?하지만 코드가 아직 변경되지 않았기 때문에 각 어셈블리에서 일부 형식을로드해야 할 수도 있습니다.

using ProtoBuf; 
using ProtoBuf.Meta; 
using System.Collections.Generic; 
using System.IO; 

namespace protobuf 
{ 
    [ProtoContract] 
    public interface IAbstraction 
    { 
     [ProtoMember(1)] 
     string Name { get; set; } 
    } 

    [ProtoContract] 
    public class Base : IAbstraction 
    { 
     static Base() 
     { 
      ProtobufTypeModels.MainModel.Add(typeof(IAbstraction), true).AddSubType(101, typeof(Base)); 
     } 

     [ProtoMember(1)] 
     public string Name { get; set; } 

     [ProtoMember(2, AsReference =true)] 
     public List<IAbstraction> Instances = new List<IAbstraction>(); 
    } 

    [ProtoContract] 
    public class Next : Base 
    { 
     static Next() 
     { 
      ProtobufTypeModels.MainModel.Add(typeof(IAbstraction), true).AddSubType(100, typeof(Next)); 
     } 

     [ProtoMember(1)] 
     public string NextName { get; set; } 
    } 

    public static class ProtobufTypeModels 
    { 
     public static readonly RuntimeTypeModel MainModel = TypeModel.Create(); 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      Base b = new Base { Name = "Alois" }; 
      b.Instances.Add(new Next { Name = "Base", NextName = "Christian" }); 
      b.Instances.Add(new Base { Name = "SecondBase", Instances = b.Instances }); 
      var mem = new MemoryStream(); 
      ProtobufTypeModels.MainModel.Serialize(mem, b); 
      mem.Position = 0; 
      var deser = (Base) ProtobufTypeModels.MainModel.Deserialize(mem, null, typeof(Base)); 
     } 
    } 
} 

답변

1

임의의 생각 : 당신이 초기화를 완료하고 디스크에 구운 시리얼을 작성 한 후 사용 .Compile(serializerName,dllPath); 그런 다음 참조 할 수 있습니다. new SerializerName()을 사용하여 인스턴스를 만들고 .Serialize 등 방법 을 사용하십시오.. dll은 절대로 변경되지 않습니다. 즉, 메타 데이터를 처리하지 않아도된다는 의미입니다.; 아무 반사도, IL 방출하지 않는다.

은 아마도 구성을 저장하는 측면에서 좀 더 부드럽지 만, protobuf-net은 현재 그것을 지원하기 위해 직접 아무것도 추가하지 않는다. 시작할 때 단순히 소비하는 맞춤형 구성 데이터를 가지고있는 것이 더 적절할 것입니다.

+0

저장된 모든 파일을로드해야하는 장기 실행 프로세스의 경우 현재 AppDomain에로드 된 어셈블리가 너무 많아 (수천) 발생하여 새 어셈블리를 메모리 누수 문제가 발생할 수 있으므로 어셈블리를 직렬화하는 것이 가장 좋은 방법은 아닙니다. . Model.Add 및 AddSubtype 호출을 기록하고 스트림 앞쪽에이 매개 변수를 저장하여 형식을 다시 deserialize해야 할 때 API 호출 재생을 수행 할 것이라고 생각합니다. –

관련 문제