Protobuf-net dynamictype array
dynamictype, object, protobuf-net, serialization
Solution
Your difficulty is explained (albeit not fully) by the restrictions on `DynamicType` mentioned here at the former project site for protobuf-net:
`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.
So, what exactly is meant by a contract type? As stated, primitive types are not contract types, but is that all? From 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):
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. ...
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.
So serialization of a "contract type" corresponds to "normal serialization" in this article -- and collections are not contract types. This explains the `Dynamic type is not a contract-type: TestType[]` exception message.
As a workaround, you can package your `ProtoDynamicProperty` inside a generic surrogate type that is guaranteed to correspond to a contract type and encapsulates the requisite type information, like so:
[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; }
}
Problem
I wont to do some serialization with Protobuf-net and getting folowing error for this code snippet: The error: Dynamic type is not a contract-type: TestType[] The snippet: ``` 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; } } } ``` Any ideas why this happens? I`m using 2.0.0.651 build