Protobuf-net错误:不需要类型,并且不能推断出任何合同:System.Data.DataTable

问题描述 投票:1回答:1

我需要序列化我在运行时使用ProBuf.Serializer创建的数据表,该数据表可在protobuf-net Nuget下获得。随附以下我使用过的代码示例。我遇到错误ProtoBuf.Serialzer.Serialize(stream,table);有人可以帮我解决这个问题吗?

public static void Main()
    {
        try
        {
            Process process = new Process();
            process.StartInfo.FileName = @"E:\POC\Test\GrpcServer\bin\Debug\netcoreapp3.0\GrpcServer.exe";
            process.Start();
            List<ChannelOption> channelOptions = new List<ChannelOption>()
            {
                new ChannelOption(ChannelOptions.MaxSendMessageLength, int.MaxValue)
            };
            Channel channel = new Channel("localhost:5005", ChannelCredentials.Insecure, channelOptions);
            var client = new TestingService.TestingServiceClient(channel);
            DataTable table = CreateTable(100000);
            Console.WriteLine("Starting Serialization");
            DateTime serializationStartTime = DateTime.Now;

            MemoryStream stream = new MemoryStream();
            ProtoBuf.Serializer.Serialize(stream, table);
            stream.Seek(0, SeekOrigin.Begin);
            DateTime serializationEndTime = DateTime.Now;
            byte[] arr = stream.ToArray();
            ByteString data = ByteString.CopyFrom(arr);
            Console.WriteLine("Completed Serialization");
            Console.WriteLine("Started Communication with Grpc Server");
            DateTime startGrpcTime = DateTime.Now;
            client.RecieveData(new PBData() { Data = data });
            DateTime endGrpcTime = DateTime.Now;
            Console.WriteLine("Grpc communication ended");
            Console.WriteLine($"Serialization time :{(serializationEndTime - serializationStartTime).TotalSeconds}");
            Console.WriteLine($"Grpc Communication time :{(endGrpcTime - startGrpcTime).TotalSeconds}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error:{ex.Message}");
        }
    }`
c# grpc protobuf-net serializer
1个回答
0
投票

编辑:下面的很多答案都假定您正在使用protobuf-net.Grpc;重新阅读该帖子后,这可能不是一个有效的假设-尽管实际上可以很好地解决您的问题!但是:也许您遇到的一个更简单的解决方案是将代码替换为:

DataTable table = CreateTable(100000);
Console.WriteLine("Starting Serialization");
DateTime serializationStartTime = DateTime.Now;

MemoryStream stream = new MemoryStream();
table.RemotingFormat = RemotingFormat.Binary;
table.WriteXml(stream);
stream.Seek(0, SeekOrigin.Begin); // not actually needed, note
DateTime serializationEndTime = DateTime.Now;
byte[] arr = stream.ToArray();
ByteString data = ByteString.CopyFrom(arr);
Console.WriteLine("Completed Serialization");

((当图书馆的作者说“这可能不是您的最佳选择”时,您应该可能听😉)] >>


protobuf-net是合同序列化器-它有助于序列化[[数据合同

”类型(一般意义上,而不是WCF特定意义上)。 DataTable是数据协定的相反-它没有可预测的定义形状,因此在protobuf-net中不能很好地发挥作用。历史上,我曾尝试过[[experimental来允许它们可序列化-有一些bits here,但这是protobuf-net支持的库表面的not部分,并且坦率地说:期望它会失败。我也要亲自指出:我强烈建议against使用DataTable交换数据-几乎永远不是正确的类型

除非您正在编写临时查询系统,例如作为报告工具或类似SSMS / SEDE的工具-即采用某种查询语言并返回某些事先无法得知的数据形式。

但是:这只是一个副题,可能无法控制,所以:让我们来谈谈DataTable[我认为我们应该在这里忘记“ protobuf-net”部分,而将重点放在您实际上想做的事情上。我将在这里在几行之间进行阅读,并猜测您在[[actually之后是:您正在使用protobuf-net.Grpc,并且您想要交换DataTableDataSet 。好消息是:protobuf-net.Grpc实际上并不与protobuf-net

以任何方式

绑定(默认情况下除外)。您可以添加自己的编组工厂(或工厂),以对任何类型的

category

起作用,或者对于单个类型,您可以<>,例如-完全未经测试,但是应该工作:
ProtoBuf.Grpc.Configuration.BinderConfiguration.Default.SetMarshaller( new Marshaller<DataTable>(SerializeDataTable, DeserializeDataTable)); // side note: you may want to try setting the RemotingFormat of the // DataTable you are using to Binary before sending it to gRPC static byte[] SerializeDataTable(DataTable value) { using var ms = new MemoryStream(); value.WriteXml(ms); return ms.ToArray(); } static DataTable DeserializeDataTable(byte[] value) { using var ms = new MemoryStream(value); var obj = new DataTable(); obj.ReadXml(ms); return obj; } 请注意,您需要将自定义编组程序告诉客户端和服务器。另请注意:marshaller选择是由protobuf-net.Grpc根据服务上传递的数据做出的-我的意思是:发送数据的参数类型和接收数据的返回类型。这意味着以上内容仅在DataTable是这两个中的一个时才有效;这样就可以了:
ValueTask<SomeContractType> SendAsync(DataTable blah);
ValueTask<DataTable> ReceiveAsync(SomeContractType blah);
ValueTask<DataTable> SendAndReceiveAsync(DataTable blah);

但是不会:

ValueTask<HazDataTable> WrappedAsync(HazDataTable blah); // ... [ProtoContract] public class HazDataTable { [DataMember(1)] public DataTable TheData {get;set;} } 因为在Wrapped情况下,protobuf-net.Grpc解析了HasDataTable的编组器

并且从不看里面

-这意味着编组器将是protobuf-net-并且protobuf-net不起作用用DataTable
© www.soinside.com 2019 - 2024. All rights reserved.