2017-03-04 5 views
2

무시합니다. 나는 이 (가) itemType: null, defaultType: null을 제공함으로써 콜렉션처럼 보이는 사실을 무시하도록 AddField을 강제로 시도합니다.protobuf - 그물 AddField 내가이 데이터 구조 선언이 IgnoreListHandling

그럼에도 불구하고 member.ItemType은 null이 아니며 member.DefaultType도 null이 아닙니다. 그리고 some_objects 생성 protorepeated 필드되었다 :

message NotACollection { 
    optional int32 some_data = 1 [default = 0]; 
} 
message NotACollectionHolder { 
    optional NotACollection some_objects = 1; 
} 

어떻게 그것을 얻을 수 있습니다

message NotACollectionHolder { 
    repeated int32 some_objects = 1; 
} 

내가 proto는 다음과 같이 기대? 내가 도대체 ​​뭘 잘못하고있는 겁니까? protobuf-net이이 필드를 non collection 필드처럼 취급하도록하려면 어떻게해야합니까?

미리 감사드립니다.

답변

0

이것이 protobuf-net의 버그라는 것을 알게되었습니다.

if (model.FindWithoutAdd(miType)?.IgnoreListHandling == true) 
{ 
    itemType = null; 
    defaultType = null; 
} 
else 
    ResolveListTypes(model, miType, ref itemType, ref defaultType); 

다른과 기능

private ValueMember AddField(int fieldNumber, string memberName, Type itemType, Type defaultType, object defaultValue) 

대체 라인

ResolveListTypes(model, miType, ref itemType, ref defaultType); 

에서 파일 MetaType.cs에서 : 그것을 해결하는 첫 번째 방법은 protobuf - 네트의 소스 코드를 변경하는 것입니다 필드를 추가 한 후 리플렉션을 사용하여 ValueMember ~ null 개체의 itemTypedefaultType 필드를 설정하는 것입니다.

ValueMember m = meta.AddField(++last_field_number, f.Name, f.ItemType, f.DefaultType); 
m.GetType().GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(m, null); 
m.GetType().GetField("defaultType", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(m, null); 

희망이 있으면 도움이 될 것입니다.

0

RuntimeTypeModel API의 버그 또는 제한 사항 일 수 있습니다.

ValueMember이 컬렉션인지 여부를 확인하는 방법은 RuntimeTypeModel.ResolveListTypes()입니다. 들어오는 itemType이 null 일 때 컬렉션 항목 유형을 추론합니다. 수행하여 예를 들어, 정적 속성을 사용 NotACollectionHolder에 대한 계약을 구축 할 때 :

var model = TypeModel.Create(); 
var schema = model.GetSchema(typeof(NotACollectionHolder)); 

다음 ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour(bool isEnum, ProtoMemberAttribute normalizedAttribute)는이 ValueMember를 초기화 만들라고합니다.

 // check for list types 
     ResolveListTypes(model, effectiveType, ref itemType, ref defaultType); 
     // but take it back if it is explicitly excluded 
     if(itemType != null) 
     { // looks like a list, but double check for IgnoreListHandling 
      int idx = model.FindOrAddAuto(effectiveType, false, true, false); 
      if(idx >= 0 && model[effectiveType].IgnoreListHandling) 
      { 
       itemType = null; 
       defaultType = null; 
      } 
     } 

공지 사항 IgnoreListHandling에 대한 명시 적 검사에는 다음과 같은 논리가? 이렇게하면 some_objects이 컬렉션으로 직렬화되지 않게됩니다.

var model = TypeModel.Create(); 
var meta = model.Add(typeof(NotACollectionHolder), false); 
var member = meta.AddField(1, "some_objects", null, null); 
var schema = model.GetSchema(typeof(NotACollectionHolder)); 

을 다음 MetaType.AddField(int fieldNumber, string memberName, Type itemType, Type defaultType, object defaultValue)가 호출 될 때, 단순히 않는 : IgnoreListHandling에 대한 확인이없는

 ResolveListTypes(model, miType, ref itemType, ref defaultType); 

공지 사항을 다음과 같이

반대로, 경우 프로그래밍 ValueMember을 추가? 이것이 문제의 원인입니다.

불행히도 ValueType.itemType은 읽기 전용이며 MetaType[int fieldNumber]은 get 전용이므로이 문제를 해결하기 위해 간단한 API가없는 것 같습니다. reporting an issue을 고려해보십시오.내가 찾을 수

유일한 해결 방법은 지금처럼 NotACollectionHolder 유형에 대한 대리를 소개하는 것입니다 : 다음

[ProtoContract] 
internal class NotACollectionHolderSurrogate 
{ 
    [ProtoMember(1)] 
    internal NotACollectionSurrogate some_objects; 

    public static implicit operator NotACollectionHolder(NotACollectionHolderSurrogate input) 
    { 
     if (input == null) 
      return null; 
     return new NotACollectionHolder { some_objects = input.some_objects }; 
    } 

    public static implicit operator NotACollectionHolderSurrogate(NotACollectionHolder input) 
    { 
     if (input == null) 
      return null; 
     return new NotACollectionHolderSurrogate { some_objects = input.some_objects }; 
    } 
} 

[ProtoContract] 
internal class NotACollectionSurrogate 
{ 
    [ProtoMember(1)] 
    public int some_data; 

    public static implicit operator NotACollection(NotACollectionSurrogate input) 
    { 
     if (input == null) 
      return null; 
     return new NotACollection { some_data = input.some_data }; 
    } 

    public static implicit operator NotACollectionSurrogate(NotACollection input) 
    { 
     if (input == null) 
      return null; 
     return new NotACollectionSurrogate { some_data = input.some_data }; 
    } 
} 

그리고는 수행

var model = TypeModel.Create(); 
model.Add(typeof(NotACollectionHolder), false).SetSurrogate(typeof(NotACollectionHolderSurrogate)); 

var schema = model.GetSchema(typeof(NotACollectionHolder)); 

생성 된 계약은 필요하다 :

message NotACollectionHolderSurrogate { 
    optional NotACollectionSurrogate some_objects = 1; 
} 
message NotACollectionSurrogate { 
    optional int32 some_data = 1 [default = 0]; 
}