WCF的近似测量的消息大小的编程方式
-
21-08-2019 - |
题
给予一类:
[DataContract]
public sealed class ChangedField
{
[DataMember(Name="I")] public ushort FieldId { get; set; }
[DataMember(Name="V")] public object Value { get; set; }
}
查看表明,当发送的通过WCF TCP结合,编码的消息是二进制(打印的字符,但是你的想法):
ChangedFielda.I..a.V....e:double..e http://www.w3.org/2001/XMLSchema.s.....a.
但是,如果我serialise的一个实例,这种类型的像这样...
var ser = new DataContractSerializer(typeof(ChangedField));
var stream = new MemoryStream();
ser.WriteObject(stream, new ChangedField { FieldId = 1, Value = 1.23d });
...然后流含有的肥皂XML类似这样的:
<ChangedField>
<I>1</I>
<V i:type="a:double" xmlns:a="http://www.w3.org/2001/XMLSchema">1.23</V>
</ChangedField>
所以我的问题是 我怎么可以控制 DataContractSerializer
产生的二进制代表在我自己的代码?
作为一个旁白:
你可以看到的消息是臃肿的事实, object
财产必须有其类型的编码(因此URI)。我要改变这种使用定义的二进制编码,作为在我的情况下,该领域的ID确定的类型(在这种情况下, double
).
解决方案
在TCP绑定默认使用,因为在那里你只是序列化数据契约转换成XML在第二个例子中,二进制消息编码器。什么与二进制消息编码器发生的是,它基本上提供而不是XML与产生一个专有的二进制格式的自定义的XmlWriter执行数据合同串行器。
如果你想用不同的结合(比如HTTP)使用,那么你需要创建一个自定义的,而不是绑定和添加的 BinaryMessageEncodingElement 元件,而不是正常TextMessageEncodingElement。
其他提示
您无法控制DataContractSerializer的 - 但你可以在你的WCF控制约束力,是否会序列化到文本格式或二进制
当你发现你自己,NetTcpBinding的默认为二进制信号,因此是非常紧凑和快速。基于HTTP的绑定默认为文本的互操作性的缘故,因此更详细和更小高性能的。
但是,创建自己的基于二进制的HTTP绑定什么能阻止你 - 如果的你愿意接受外部客户端互操作性是窗外,如果你做的。这将仅适用于使用相同的自定义绑定您自己的内部客户的工作。
基本上,你需要做的是建立自己的自定义从头结合的东西 - 在代码或配置。在配置它很容易:
<system.serviceModel>
<bindings>
<customBinding name="binaryHttpBinding">
<binaryMessageEncoding />
<httpTransport />
</customBinding>
</bindings>
</system.serviceModel>
您的两个最小部分必须强>指定是一个消息编码和传输协议 - 别的是可选的
现在,你可以指定你的WCF服务和客户端,这样他们就会使用这个新的自定义二进制过HTTP绑定:
<system.serviceModel>
<services>
<service name="YourService">
<endpoint address="http://whatever.com:8888/YourAddress"
binding=binaryHttpBinding"
contract="IYourContract" />
</service>
</services>
</system.serviceModel>
(和相同的方法也适用于在<client>
部客户端,当然)。
有你有它 - 它不以任何方式,形状或形式的代码控制的DataContractSerializer的问题 - 只需要创建一个自定义绑定,并使用它
马克
修改强>(后评论左):结果 那么,WCF确实很可扩展的,所以你可以在路上做类似的消息督察出的客户端。你可以写这样的消息督察(从 IClientMessageInspector <派生/ A>),其不执行任何操作而检查该消息,并测量其大小和写入到一个文件或数据库
你看了在的DataContractSerializer <文档/ A>
要使用的DataContractSerializer, 首先创建一个类的实例 和物体适合于写入 或读取的格式;例如,一个 在的XmlDictionaryWriter的实例。 然后调用writeObject方法来 持久化数据。检索数据, 创建一个对象适合 读取的数据格式(诸如 XmlDictionaryReader为XML 文件)并调用的readObject 方法
您然后想了解的XmlDictionaryWriter
这里是最简单的解决方案我可以找到问题:
static byte[] Serialise(object obj, MessageEncodingBindingElement encoding)
{
encoding.MessageVersion = MessageVersion.Soap12;
var stream = new MemoryStream();
var message = Message.CreateMessage(MessageVersion.Soap12, "", obj,
new DataContractSerializer(obj.GetType()));
encoding.CreateMessageEncoderFactory().Encoder.WriteMessage(message, stream);
return stream.ToArray();
}
...在哪里 encoding
参数是:
new TextMessageEncodingBindingElement()
...或者...
new BinaryMessageEncodingBindingElement()
...取决于你是否想要的文字或二进制的格式。
谢谢来 tomasr 的 链接到他的文章对这个话题.