为什么有些内置类型在我编译 typeModel 时不起作用?

Why don't some Built-in types work when I compile typeModel?

当我编译 Type 模型字典时停止工作。

    [Test]
    public void TestCompileSerialization()
    {
        var data = new Dictionary<int, int>();
        data[1] = 1;

        var typeModel = TypeModel.Create();
        var compiledTypeModel = typeModel.Compile();

        using (var memory = new MemoryStream())
        {
            compiledTypeModel.Serialize(memory, data);
        }
    }

这个测试抛出

Type is not expected, and no contract can be inferred: System.Collections.Generic.KeyValuePair`2[[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]

我是否需要将我可能想要序列化的每个字典都添加到 TypeModel 中,或者还有其他一些方法?

顺便说一句,当我想预编译序列化程序时,我不明白为什么我必须制作所有内容 public?

是的,当您创建自己的类型模型时,您需要提前告诉它要包含什么 - 否则它不知道要支持什么。理想情况下,这包括您将序列化为根类型的所有类型,因此:如果您要序列化字典:告诉它。在内部,protobuf-net v2 实际上并没有特殊情况的字典——它将它们视为一个类似列表的类型序列 (KeyValuePair<TKey, TValue>),恰好看起来很像它可以猜测的类型"tuple"; protobuf-net v3 确实知道更多关于字典的知识,但是......你还是提前告诉它更好。

BTW I don't get why do I have to make everything public when I want to precompile serializers?

有两种类型的预编译;也许你 实际上 只是想要 CompileInPlace()(而不是 Compile()),它保留了现有的 RuntimeTypeModel,但在幕后使用 IL-emit 来创建轻量级垫片方法来完成这项工作;使用这种方法时,可以绕过可访问性验证检查,允许我访问非 public 的任何内容;但是,当您使用 Compile() 时,您是在真实程序集中创建真实类型(只是:在内存中),而当您使用 that 时:您 不能 绕过可访问性检查(以及其他一些验证检查);这意味着我遵守与您在 C# 编译器中相同的规则:如果它不是 public,我就不能碰它。