2014-05-12 1 views
1

파일에 데이터를 저장하는 라이브러리를 교체해야합니다 (serialize/deserialize) 이 라이브러리는 현재 BinaryFormatter를 사용하지만 큰 목록에는 속도가 느립니다. 여기에 많은 게시물 stackoverflow에 protobuf 정말 performant 보여, 그래서 그것을 사용하려고합니다. 많은 코드를 다시 작성하지 않고도 교체를 만들기 위해protobuf로 binaryformatter 바꾸기

, 내 요구 사항은 다음과 같습니다 나는 (대부분의 시간 T가 DataContract와 함께 표시됩니다 Store<T>(T data)와 인터페이스했듯이

  • 는 일반 데이터를 직렬화해야/또는 Serializable 특성)
  • protobuf 특성을 추가하기 위해 모든 다른 objets 클래스를 수정할 수 없으므로이 특성을 사용하지 않는 일반 메서드가 필요합니다.
  • T 객체 스키마 변경 (즉, 새 속성), 생성 된 모든 파일은 더 이상 사용되지 않으며 삭제됩니다/다시

내 제 순진 구현은 다음과 같습니다 :이 예외를 가지고 다음

public bool Store<T>(string key, T data) 
{ 
    var formatter = Serializer.CreateFormatter<T>(); 
    using (var fileStream = new FileStream(this.GetFilePath(key), FileMode.Create)) 
    { 
     formatter.Serialize(fileStream, data); 
     return true; 
    } 
} 

하지만을 :

유형이 예상되지 않습니다, 어떤 계약 유추 할 수 없습니다 : 내를 .Application.Namespace.ShortcutData

현재 저는 조금 붙어 있습니다. protobuf-net을 사용하는 방법에 대한 좋은 지침서를 찾지 못했습니다.

protobuf를 사용하여 이러한 요구 사항에 도달 할 수 있습니까? 이 작업을 수행하는 방법에 대한 좋은 지침이 있습니까?

편집 :

문제는 참으로 내가 (드) 데이터를 직렬화하는 방법을 protobuf 말할 필요가있다. 여기 내가 지금 무엇을 가지고 :

주요 코드 등록 방법에
public bool Store<T>(string key, T data) 
{ 
    this.Register<T>(); 
    var formatter = Serializer.CreateFormatter<T>(); 
    using (var fileStream = new FileStream(this.GetFilePath(key), FileMode.Create)) 
    { 
     formatter.Serialize(fileStream, data); 
     fileStream.Close(); 
     return true; 
    } 
} 

:이 깨끗한 코드가 아닙니다 알고

protected void Register(Type type) 
{ 
    if (type.IsGenericType) 
    { 
     var arguments = type.GetGenericArguments(); 
     foreach (var argument in arguments) 
      this.Register(argument); 
    } 

    if (!this._registeredTypes.Contains(type) && !type.IsValueType) 
    { 
     this._registeredTypes.Add(type); 
     var properties = type.GetProperties(); 
     foreach (var property in properties) 
     { 
      this.Register(property.PropertyType); 
     } 

     try 
     { 
      ProtoBuf.Meta.RuntimeTypeModel.Default 
       .Add(type, false) 
       .Add(properties 
        .Where(p => p.CanWrite) 
        .OrderBy(x => x.Name) 
        .Select(x => x.Name) 
        .ToArray()); 
     } 
     catch 
     { 
      // I've a problem here: I sometime have an error for an already registered type (??) 
     } 
    } 
} 

, 그러나 이것은 기존의 단지에서-대체 코드와 함께 protobuf와 완전한 재 작성은 두 번째 단계로 이어질 것입니다.

답변

2

나는 단지 Protobuf-net으로 놀기 시작했습니다. 제 대답은 어떤 식 으로든 "올바른"방법으로 생각하지 마십시오. Marc Gravell은 의심의 여지없이 어느 시점에서 당신이 반드시 메모 해 두어야 할 대답을 제공 할 것입니다.

.. 그러나 요즘 내가 쓴 개념의 증명은 내가 일련의 클래스를 순식간에 빨리 얻을 것을 요구했다. 이를 위해 .. 나는이 함께했다 :

var assembly = Assembly.Load("Assembly.Name.Here"); 

foreach (var type in assembly.GetTypes().Where(x => typeof (IInterfaceEachClassImplements).IsAssignableFrom(x))) { 
    RuntimeTypeModel 
     .Default 
     .Add(type, false) 
     .Add(type.GetProperties() 
      .Select(x => x.Name) 
      .ToArray()); 
} 

기본적으로,이 적용된 각 그들은 모두 구현하는 인터페이스를 기반으로 protobuf - 그물 typemodel에 클래스 ..없는 속성을로드합니다.

어쨌든 이것은 올바른 방향으로 당신을 안내합니다.

+0

'GetProperties()'는 순서에 대해 아무런 보장도하지 않으며 암시 적 필드 번호를 결정하기 때문에 순서가 실제로 중요합니다. –

+0

나는 생각났다. 그러나 내가 말했듯이 : 개념 증명. 내가 물건을 주문하면 그 차이가 생길까요? 내 실제 코드는 이제 필자가 특별히 작성해야하는 것을보다 효과적으로 제어 할 수 있도록 ProtoReader와 ProtoWriter를 향하고있다. GetProperties 호출을 제외하고 덜 취약하도록하는 권장 사항이 있습니까? –

+0

'ProtoReader'와'ProtoWriter'는 protobuf-net이 내부적으로 필요로하는 것에 매우 적합합니다; 물론 직접 사용할 수도 있지만 일반적으로 사용되는 것은 아닙니다. 다시 덜 부서지기 쉽습니다. 솔직히 말해서, 나는 속성 접근법을 사용합니다. 더 간단합니다. 직렬화하려는 유형이 사용자가 아닌 경우 : 직렬화 대리를 사용하거나 직렬화를 위해 별도의 DTO 모델을 작성하십시오. –

2

ShortcutData은 무엇입니까? protobuf 형식에는 형식 메타 데이터가 포함되어 있지 않으므로 엔진에 데이터 매핑 방법에 대한 지식이 필요합니다. 이것은 다양한 속성을 통해 다양한 방법으로 수행 할 수 있습니다. 맵은 RuntimeTypeModel과 관련된 코드를 통해 런타임에 지정할 수도 있습니다. 예를 들어, 우리의 ShortcutData 보이는 경우처럼 :

public class ShortcutData { 
    public int Key {get;set;} 
    public string Link {get;set;} 
} 

그리고 우리는 간단하게 할 수있는 : 12이 protobuf 필드 식별자가 될 것이다

[ProtoContract] 
public class ShortcutData { 
    [ProtoMember(1)] 
    public int Key {get;set;} 
    [ProtoMember(2)] 
    public string Link {get;set;} 
} 

. 직렬화하려면 형식 기 API를 사용할 필요가 없습니다. 간단히 :

public bool Store<T>(string key, T data) 
{ 
    using (var fileStream = File.Create(GetFilePath(key))) 
    { 
     Serializer.Serialize<T>(fileStream, data); 
     return true; 
    } 
} 
+0

ShortcutData는 DTO입니다. 문제는 우리가 1000+ DTO를 가지고있어서 주어진 시간에 모든 DTO를 업데이트 할 수 없다는 것입니다. 그것은 두 번째 단계에있을 것입니다. 그래서 나는 어떤 속성이나 대리자없이 그것을하려고 노력한다. – Fabske

관련 문제