我们使用protobuf-net对公共协议基于Google Protocol Buffers的应用程序中的消息进行序列化和反序列化.该库非常出色,涵盖了除此之外的所有要求:我们需要在消息实际序列化之前找出序列化的消息长度(以字节为单位).
这个问题已经在一年半前提出过,根据Marc的说法,唯一的方法就是序列化到MemoryStream并.Length随后读取属性.在我们的例子中这是不可接受的,因为MemoryStream在幕后分配一个字节缓冲区,我们必须避免这种情况.
来自同一回复的这一行给了我们希望它毕竟是可能的:
如果你澄清用例是什么,我相信我们可以轻松地提供它(如果它还没有).
这是我们的用例.我们有大小在几个字节和两兆字节之间变化的消息.应用程序预先分配用于套接字操作和序列化/反序列化的字节缓冲区,一旦预热阶段结束,就不能创建额外的缓冲区(提示:avoding GC和堆碎片).字节缓冲区基本上是合并的.我们还希望尽可能避免在缓冲区/流之间复制字节.
我们提出了两种可能的策略,它们都需要预先设置邮件大小:
Socket.Send.我们必须知道下一条消息何时无法放入缓冲区并停止序列化.如果没有消息大小,实现此目的的唯一方法是等待异常发生Serialize.Socket.Send.为了从池中检出具有适当大小的字节缓冲区,我们需要知道序列化消息有多少字节.因为协议已经定义(我们不能改变它)并且要求消息长度前缀为Varint32,所以我们不能使用SerializeWithLengthPrefix方法.
那么是否可以添加一种估计消息大小而无需序列化到流中的方法?如果它不适合图书馆的当前功能集和路线图,但是可行,我们有兴趣自己扩展图书馆.我们也在寻找替代方法,如果有的话.
我在创建T4模板时遇到问题,该模板可用于从Visual Studio和MSBUild生成相对简单的C#代码.模板引用DLL,该DLL驻留在项目的输出路径中.除此之外,它是一个相当简单的模板,循环遍历域对象的集合,并为每个域对象输出测试方法.
MSDN建议使用以下方法在两个主机中使用属性:
<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
<myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>
<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
<T4ParameterValues Include="myLibFolder">
<Value>$(myLibFolder)</Value>
</T4ParameterValues>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
不幸的是,这只是行不通.通过MSBuild执行时,我收到以下错误:
Compiling transformation: Metadata file '$(myLibFolder)Cmc.SpeedWays.Core.Testing.dll' could not be found
Run Code Online (Sandbox Code Playgroud)
有没有人设法解决这个问题或至少找到一个可接受的解决方法?我们正在使用VS2012和MSBUild 4.0.