我需要序列化我在运行时使用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}");
}
}`
编辑:下面的很多答案都假定您正在使用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,并且您想要交换DataTable
或DataSet
。好消息是: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
的编组器并且从不看里面
DataTable
。