protobuf-net.Grpc 序列化接口

protobuf-net.Grpc serializing Interfaces

我在 Protobuf-net.grpc 中使用 CodeFirst 序列化接口时遇到了一些困难。它是 DataContract 中的一个 DataMember。当我在一个简单的控制台应用程序中使用它时它工作正常,但是当我尝试在具有相同引用的不同项目中使用它时,它不会序列化。当在 gRPC 服务器上完成 AddCodeFirst 时,我也可以在 Visual studio 输出中看到此错误:

Exception thrown: 'System.InvalidOperationException' in protobuf-net.dll

这是我的项目和虚拟应用程序中的 DataContract 代码

using ProtoBuf;

namespace ProtoBufTesting.Prepare
{
    [DataContract, ProtoContract]
    public class ExtensionData
    {
        public ExtensionData() { }

        public ExtensionData(
            string extensionName,
            string packageIdentifier,
IExtensionCertificateCollection collection)
        {
            this.ServiceName = extensionName;
            this.PackageIdentifier = packageIdentifier;
            this.CertificateCollection = collection;
        }

        [DataMember]
        [ProtoMember(1)]
        public string ServiceName
        {
            get; private set;
        }

        [DataMember]
        [ProtoMember(4)]

        public string PackageIdentifier
        {
            get; private set;
        }

        [DataMember]
        [ProtoMember(5)]

        public IExtensionCertificateCollection CertificateCollection { get; private set; }
    }
}

这是 IExtensionCertificateCollection 接口,它具有在我的示例项目中工作的 ProtoContract 装饰器。

namespace ProtoBufTesting
{
    [ProtoContract]
    public interface IExtensionCertificateCollection
    {

        IExtensionCertificate GetByThumbprint(string thumbprint);

        IEnumerable<IExtensionCertificate> AllCertificates { get; }
    }
}

这是使用 ExtensionData 数据合约的服务合约

[ServiceContract(Namespace = "blah")]
public interface IRTC
{

    [OperationContract]
    ExtensionData PrepareExtension(PrepareExtensionInput input);

}

如果您在下面看到,这就是我进行 Code First 设置的方法。 除了在我做同样事情的第二个项目中,这工作得很好。我真的不确定如何调试它。我做一个示例控制台应用程序的原因是测试接口是否使用 ProtoContract 装饰器进行序列化并且它们仅使用 ProtoContract 装饰器就成功了......但是当我开始在一个更大的项目(相同的接口定义和数据契约)中使用它时,它只是似乎没有序列化 DataContract。当我从 Datamember 中删除该接口时,它只会序列化 DataContract。有什么想法我应该如何调试它以找出造成这种情况的原因吗?我已经坚持了几个小时。除了 InvalidOperationException,我在 VS 输出中没有看到任何其他错误。

Server server = new Server
            {
                Ports = { new ServerPort("localhost", ServerPort.PickUnused , ServerCredentials.Insecure) }
            };

            server.Services.AddCodeFirst(new RTC());
            server.Start();
            int port = server.Ports.Single().BoundPort;

            Console.WriteLine("server listening on port " + port);

            GrpcClientFactory.AllowUnencryptedHttp2 = true;

            Channel channel = new Channel("localhost", port, ChannelCredentials.Insecure);
            

            var rtc = channel.CreateGrpcService<IRTC>();

更新:

我想出了一个不同的方法来 'debug' 这个 - 使用下面的这个方法。它解析了我要序列化的对象的架构。对这个特定对象进行 try catch 至少给了我一个错误! “标签必须是正整数”。我发现了这个问题并修复了它。

ProtoBuf.Meta.RuntimeTypeModel.Default.GetSchema(typeof(ExtensionData));

但在那次错误之后,我仍然继续获取以前的静止图像,但似乎无法解决。我在单元测试方法下 运行 它只在 AddCodeFirst 期间显示像这样的高级错误 - 我在 AddCodeFirst 中添加了一个 TraceWriter,这就是它所说的 -

[warning] Type cannot be serialized; ignoring: ExtensionData
[warning] Signature not recognized for PrepareExtension; method will not be bound

我该如何进一步调查这个问题?这与我仍然得到的先前错误有关:

抛出异常:'System.InvalidOperationException' in protobuf-net.dll

我终于解决了这个问题。许多与接口(和其他接口)关联的类型没有被正确反序列化。我没有在任何错误日志中看到这一点,但这使得很难找到..在线搜索/通过代码隐藏查找protobuf-grpc..它看起来像是添加了需要反序列化的所有类型的显式注册需要接口,否则无法使用

我不知道是否有更好的方法来做到这一点,但这在 grPC AddCodeFirst 之前是必需的,否则服务不会在没有先完成此操作的情况下注册这些方法。

ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(IExtensionCertificateCollection), true).AddSubType(1, typeof(ExtensionCertificateCollection)); 
ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(IExtensionCertificateCollection), true).AddSubType(1, typeof(NewCollectionCerts));
server.Services.AddCodeFirst(new FakeRTC(), log: writelogs);