I am getting the following error message when trying to serialize List<Tuple<string, Type, object>>
: No Serializer defined for type: System.Type
I tried both, just serializing the above collection or serializing a class that has the same collection defined as protoMember. Both result in the same error message.
Is this a non-supported type? I assume it is supported and I overlooked something else but maybe I am incorrect?
Thanks for any pointers that may help resolve this...
Edit:
Support for Type
serialization is included in r580
protobuf-net is intended to serialize your data, not your implementation; Type
is an implementation detail. Strictly speaking, it wouldn't be hugely hard to add (some of the implementation-specific details already essentially end up storing Type
info, via the assembly-qualified-name), but: it isn't a key scenario, and in many ways is not something I would encourage you to serialize - the whole point of protocol buffers is that you can load the data on any platform, with version tolerance a key feature. Storing Type
information violates both of these.
It should also be noted that most other serializers (except perhaps BinaryFormatter
, which already breaks every rule of platform/version-tolerance) will also refuse to serialize a Type
; XmlSerializer
, DataContractSerializer
, JavaScriptSerializer
etc all throw an exception for this scenario (I just checked them).
Additionally: object
is even less supportable, unless you use the DynamicType
feature.
Here's how it could be done via a surrogate on Type
:
using ProtoBuf;
using ProtoBuf.Meta;
using System;
using System.Runtime.Serialization;
static class Program
{
public static void Main(string[] args)
{
// register a surrogate for Type
RuntimeTypeModel.Default.Add(typeof(Type), false)
.SetSurrogate(typeof(TypeSurrogate));
// test it
var clone = Serializer.DeepClone(new Foo { Type = typeof(string) });
}
}
[ProtoContract]
class TypeSurrogate
{
[ProtoMember(1)]
public string AssemblyQualifiedName { get; set; }
// protobuf-net wants an implicit or explicit operator between the types
public static implicit operator Type(TypeSurrogate value)
{
return value==null ? null : Type.GetType(value.AssemblyQualifiedName);
}
public static implicit operator TypeSurrogate(Type value)
{
return value == null ? null : new TypeSurrogate {
AssemblyQualifiedName = value.AssemblyQualifiedName };
}
}
[DataContract]
public class Foo
{
[DataMember(Order=1)]
public Type Type { get; set; }
}