2013-07-15 31 views
3

我不會做一些序列化與protobuf網並獲得如下因素錯誤此代碼段:protobuf網dynamictype陣列

錯誤:

Dynamic type is not a contract-type: TestType[]

的片段:

using System.IO; 
namespace QuickStart 
{ 
    class Program 
    { 
     static void Main() 
     { 
      //FileAccess.ShowFileAccess(); 
      //Sockets.ShowSockets(); 

      var dto = new DataTransferType 
      { 
       ProtoDynamicProperty = new TestType[] 
       { 
        new TestType {UselessProperty="AAA"}, 
        new TestType{UselessProperty="BBB"}, 
        new TestType{UselessProperty="CCC"} 
       } 
      }; 

      using (MemoryStream testStream = new MemoryStream()) 
      { 
       ProtoBuf.Serializer.SerializeWithLengthPrefix(testStream, dto, ProtoBuf.PrefixStyle.Base128); 
      } 
     } 


    } 
    [ProtoBuf.ProtoContract] 
    struct TestType 
    { 
     [ProtoBuf.ProtoMember(1)] 
     public string UselessProperty { get; set; } 
    } 

    [ProtoBuf.ProtoContract] 
    class DataTransferType 
    { 
     [ProtoBuf.ProtoMember(1, DynamicType = true)] 
     public object ProtoDynamicProperty { get; set; } 
    } 
} 

任何想法爲什麼發生這種情況?我真的使用2.0.0.651構建

+0

剛走回答[這個問題] (https://stackoverflow.com/questions/39208449/protobuf-net-how-to-serialize-complex-collection/39214319#39214319)我意識到我也知道這個老問題的答案,所以我繼續回答它,儘管它的年齡。 – dbc

回答

2

你的困難進行了說明(雖然不是全部)通過DynamicType限制在former project site提到here爲protobuf網:

DynamicType - stores additional Type information with the type (by default it includes the AssemblyQualifiedName , although this can be controlled by the user). This makes it possible to serialize weak models, i.e. where object is used for property members, however currently this is limited to contract types (not primitives), and does not work for types with inheritance (these limitations may be removed at a later time). Like with AsReference , this uses a very different layout format.

那麼,究竟究竟是由合同類型?如前所述,原始類型不是合約類型,但是全部?從Protobuf-net: the unofficial manual: Forms of type serialization in protobuf-net

I would say there are five fundamental kinds of [de]serialization that protobuf-net supports on a type-by-type basis (not including primitive types):

  1. Normal serialization. In this mode, a standard protocol buffer is written, with one field in the protocol buffer for each field or property that you have marked with ProtoMember, or that has been auto-selected by ImplicitFields. ...

  2. Collection serialization. If protobuf-net identifies a particular data type as a collection, it is serialized using this mode. Thankfully, collection types do not need any ProtoContract or ProtoMember attributes, which means you can serialize types such as List and T[] easily...

    <snip>

    Protobuf-net serializes a collection using a "repeated" field (in protocol buffer lingo). Therefore, you should be able to safely change collection types between versions. For example, you can serialize a Foo[] and later deserialize it into a List.

因此,一個「契約型」的系列化對應於「正常序列」在這篇文章中 - 和收款都是合同類型。這解釋了Dynamic type is not a contract-type: TestType[]異常消息。

作爲一種變通方法,您可以打包ProtoDynamicProperty這是保證符合合同類型和封裝所需類型的信息,像這樣的通用替代型內:

[ProtoContract] 
public abstract class TypedObjectSurrogate 
{ 
    protected TypedObjectSurrogate() { } 

    [ProtoIgnore] 
    public abstract object ObjectValue { get; } 

    public static object CreateSurrogate<T>(T value) 
    { 
     if (value == null) 
      return new TypedObjectSurrogate<T>(); 
     var type = value.GetType(); 
     if (type == typeof(T)) 
      return new TypedObjectSurrogate<T>(value); 
     // Return actual type of subclass 
     return Activator.CreateInstance(typeof(TypedObjectSurrogate<>).MakeGenericType(type), value); 
    } 
} 

[ProtoContract] 
public sealed class TypedObjectSurrogate<T> : TypedObjectSurrogate 
{ 
    public TypedObjectSurrogate() : base() { } 

    public TypedObjectSurrogate(T value) 
     : base() 
    { 
     this.Value = value; 
    } 

    [ProtoIgnore] 
    public override object ObjectValue 
    { 
     get { return Value; } 
    } 

    [ProtoMember(1)] 
    public T Value { get; set; } 
} 

[ProtoBuf.ProtoContract] 
class DataTransferType 
{ 
    [ProtoBuf.ProtoIgnore] 
    public object ProtoDynamicProperty { get; set; } 

    [ProtoBuf.ProtoMember(1, DynamicType = true)] 
    object ProtoDynamicPropertySurrogate 
    { 
     get 
     { 
      if (ProtoDynamicProperty == null) 
       return null; 
      return TypedObjectSurrogate.CreateSurrogate(ProtoDynamicProperty); 
     } 
     set 
     { 
      if (value is TypedObjectSurrogate) 
       ProtoDynamicProperty = ((TypedObjectSurrogate)value).ObjectValue; 
      else 
       ProtoDynamicProperty = value; 
     } 
    } 
} 

[ProtoBuf.ProtoContract] 
struct TestType 
{ 
    [ProtoBuf.ProtoMember(1)] 
    public string UselessProperty { get; set; } 
}