为什么我只能序列化一个 Type[] 如果它被包装在一个对象中?

Why can I only serialize a Type[] if it is wrapped in an object?

我对 protobuf-net 的挣扎比我预期的要多。它在简单的情况下既美观又快速且简单,但我承认我在人迹罕至的道路上遇到了麻烦。我试图在运行时序列化和反序列化某些对象而不是使用属性,但我发现了各种问题。第一个是这个;在运行时,我可以序列化一个整数数组,但不能序列化类型,除非我先包装它们。以下是我的意思:

// Fails with 
// System.InvalidOperationException
// Type is not expected, and no contract can be inferred: System.RuntimeType
//   at ProtoBuf.Meta.TypeModel.ThrowUnexpectedType(Type type) in C:\Code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 1471
//   at ProtoBuf.Meta.TypeModel.TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, Int32 tag, Object value, Boolean isInsideList, Object parentList) in C:\Code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 172
//   at ProtoBuf.Meta.TypeModel.SerializeCore(ProtoWriter writer, Object value) in C:\Code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 194
//   at ProtoBuf.Meta.TypeModel.Serialize(Stream dest, Object value, SerializationContext context) in C:\Code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 222
//   at ProtoBuf.Serializer.Serialize[T](Stream destination, T instance) in C:\Code\protobuf-net\src\protobuf-net\Serializer.cs:line 93
//   at my bit of code

public static void SerializeMyClass()
{
    using (var ms = new MemoryStream())
    {
        Serializer.Serialize(ms, new[] {typeof(int)});
    }
}
// Works perfectly (and deserializes correctly too, not shown here for brevity)

[ProtoContract]
public class MyClass
{
    [ProtoMember(1)] public Type[] Types;
}

public static void SerializeMyClass()
{
    using (var ms = new MemoryStream())
    {
        Serializer.Serialize(ms, new MyClass {Types = new[] {typeof(int)}});
    }
}

我有什么不明白的?是否可以序列化一个类型数组而不先包装它们,如果可以,我必须做些什么不同的事情?

提前致谢!

这里的简短版本是:因为 Type 有特殊处理,并且从未在这种情况下进行过测试和修复。不过,我同意这是一种奇怪且意外的行为,并且我已在 v3 代码库 in this commit 中修复了它。不过,此修复不会返回到 v2。

请注意,在有效负载级别,包装版本和非包装版本之间没有根本区别,因此如果没有 v3 修复,这里的另一个解决方法是:使用你的 MyClass 就像你在问题中的代码。

但是!我会提醒您不要过于急切地序列化 Type;正如您在测试的有效载荷中看到的那样,Type 有一个不幸的特性,因为它对程序集元数据进行编码,如果程序集发生变化,它会变得很尴尬。在 .NET Framework 和 .NET Core 之间,程序集确实发生了变化。您可以通过在类型模型上订阅 DynamicTypeFormatting 事件来解决这个问题,但是......这只会让工作变得越来越多。