[MSDN]WCF(8)Message类

说明:本内容来自微软的webcast,讲师为徐长龙。为了用手机阅读方便点,抄录存为txt。

本次课程内容包括
- Message 类概述
- 使用 Message 类创建消息
- 读取 Message 类消息

Message 类概述
- Message 类是 WCF 的基本类
- 客户端与服务之间的所有通讯最终都会产生要进行发送和接收的 Message 实例。
- 通常不会与 Message 类直接进行交互。相反,您需要使用 WCF 服务模型构造(如数据协定、消息协定和操作协定)来描述传入消息和传出消息。
- 在以下情况下可能需要使用 Message 类
  - 需要一种替代方式来创建传出的消息内容(例如,从磁盘上的文件直接创建消息),而不是序列化.NET Framework 对象。
  - 需要一种替代方式来使用传入的消息内容(例如,需要将 XSLT 转换应用于原始 XML 内容),而不是反序列化为.NET Framework 对象。
  - 无论消息内容怎样都需要使用常规方式来处理消息(例如,在生成路由器、负载平衡器或发布-订阅系统时对消息进行路由或转发)。


在操作中使用 Message 类
- 可以将 Message 类用作操作的输入参数和/或操作的返回值。只要在操作中的任何位置使用了 Message,就必须遵从以下限制:
  - 操作不能具有任何 out 或 ref 参数。
  - 不能有一个以上的 input 参数。如果该参数存在,其类型必须为 Message 或消息协定。
  - 返回类型必须为void、Message 或消息协定类型
  [ServiceContract]
  public interface IMyService
  {
    [OperationContract]
    Message GetData();
    [OperationContract]
    void PutData(Message m);
  }


创建简单消息
- Message 类提供了静态 CreateMessage 工厂方法
  - 所有 CreateMessage 重载都采用一个类型为 MessageVersion 的版本参数,该参数指示要用于消息的 SOAP 和 WS-Addressing 版本。如果要使用与传入消息相同的协议版本,则可以用 OperationContext(从 Current 属性获取) 实例上的 IncomingMessageVersion 属性。
  - 大多数 CreateMessage 重载还具有一个字符串参数,该参数指示要用于消息的 SOAP 操作。
  - 可以将版本设置为 None 以禁用 SOAP 信封生成;消息将仅包含正文


从对象创建消息
- 另一种重载采用一个附加的 Object 参数;此重载所创建的消息的正文是给定对象的序列化表示
  public Message GetData()
  {
    Person p = new Person();
    p.name="John Doe";
    p.age=42;
    MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
    return Message.CreateMessage(ver,"GetDataResponse",p);
  }


从 XML 读取器创建消息
- 有些 CreateMessage 重载采用一个 XmlReader 或一个 XmlDicitionaryReader 而不是对象作为正文
  public Message GetData()
  {
    FileStream stream = new FileStream("myfile.xml",FileMode.Open);
    XmlDictionaryReader xdr = new XmlDictionaryReader.CreateTextReader(stream,new XmlDictionaryReaderQuotas());
    MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
    return Message.CreateMessage(ver,"GetDataResponse",xdr);
  }


创建错误消息
- 可以使用某些 CreateMessage 重载创建 SOAP 错误消息。其中一个最简单的重载采用一个用于描述错误的 MessageFault 对象作为参数
  public Message GetData()
  {
    FaultCode fc = new FaultCode("Receiver");
    MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
    return Message.CreateMessage(ver,fc,"Bad data","GetDataResponse");
  }


提取消息正文数据
- Message 类支持多种从其正文提取信息的方式。它们可以分为以下几类:
  - 将整个消息正文一次性写出到 XML 编写器。这称为“写入消息”。
  - 将 XML 读取器放在消息正文上。这使您可以在以后根据需要逐段访问消息正文。这称为“读取消息”。
  - 可以将整个消息(包括他的正文)复制到类型为 MessageBuffer 的内存中缓存区。这称为“复制消息”。


写入消息
- WriteBodyContents 方法将给定 Message 实例的正文内容写出到给定 XML 编写器。
- WriteBody 方法进行相同的操作,不同之处在于该方法将正文内容封装在适当的包装元素(如<soap:body>)中。
- 最后,WriteMessage 写出整个消息,包括SOAP包装信封和标头。请记住,如果SOAP被禁用(Version 为 MessageVersion.None ),则所有这三个方法都进行相同的操作:仅仅写出消息正文内容。
  public void PutData(Message m)
  {
    FileStream stream = new FileStream("myfile.xml",FileMode,Create);
    XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(stream);
    m.WriterBodyContents(xdw);
    xdw.Flush();
  }


读取消息
- 读取消息正文的主要方式是调用GetReaderAtBodyContents.
- 使用 GetBody 方法还可以将消息正文作为类型化对象进行访问。
  public void PutData(Message m)
  {
    Persion p = m.GetBody<Person>();
    Console.WriteLine(p.name);
  }


将消息复制到缓冲区中
- 通过调用 CreateBufferedCopy 在内存中缓冲整个消息(包括正文)。
- 缓冲区作为一个 MessageBuffer 实例返回。可以通过几种方式访问缓冲区的数据。主要方式是调用 CreateMessage 以便从缓冲区创建 Message 实例。
- 访问消息缓冲区内容的另一种方式是是 WriteMessage 将缓冲区的内容写出流中
  [OperationContract]
  public void ForwardMessage(Message m)
  {
    //Compy the message to a buffer
    MessageBuffer mb = m.CreateBufferedCopy(65536);

    //Forward to multipel recipients
    foreach (IOutputChannel channel in forwardingAddresses)
    {
      Message copy = mb.CreateMessage();
      channel.Send(copy);
    }

    //Log to a file.
    FileStream stream = new FileStream("log.xml",FileMode.Append);
    mb.WriteMessage(stream);
    stream.Flush();
  }


访问其他消息部分
- 该类提供了各种属性,以便访问除正文内容之外的其他与消息有关的信息。但是,一旦关闭了消息,将无法调用这些属性:
  - Headers 属性表示消息标头。请参见本主题稍后关于“使用标头”的部分。
  - Properties 属性表示消息属性,这些属性是附加到消息的命名数据段,且通常不会在发送消息时发出。请参见本主题稍后关于“使用属性”的部分。
  - Version 属性指示与消息相关联的SOAP 和 WS-Addressing 版本;如果禁用了 SOAP,则该属性为 None。
  - IsFault 属性在消息为 SOAP 错误消息时返回true。
  - IsEmpty 属性在消息为空时返回 true。


使用标头
public class MyService6:IMyService
{
  public void PutData(Message m)
  {
    foreach (MessageHeaderInfo mhi in m.Headers)
    {
      Console.WriteLine(mhi.Name);
    }
  }

  public Message GetData()
  {
    throw new NotImplmentedException();
  }
}

posted @ 2012-01-22 21:27  yellowwood  阅读(323)  评论(0编辑  收藏  举报
Never Give UP