给予一类:

[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>),其不执行任何操作而检查该消息,并测量其大小和写入到一个文件或数据库

这里是最简单的解决方案我可以找到问题:

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链接到他的文章对这个话题.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top