用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心编程技巧Visual C++

编程高手 实例解析C++/CLI之代理与事件

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-03-16 20:37:47


  在标号1、2、3中,定义了三个Test类型的对象,并把它们各自与实例函数Test:M包装在单独的代理类型D中。接着,在标号4中,创建了一个四入口的调用列表。

  倘若传递进来的调用列表不为空,ProcessList函数将调用在列表中除了特定对象以外的所有函数,例如,在标号5a中,没有排除任何入口,因此所有的函数都会被调用;在标号5b中,t1被排除在外,而标号5c中,与对象t2有关的两个入口都被排除了,结果输出如下:

Object t1: 100
Object t2: 100
Object t3: 100
Object t2: 100
Object t2: 200
Object t3: 200
Object t2: 200
Object t1: 300
Object t3: 300

  在标号6b中,调用了Clone创建了代理cd4的一个副本,这个函数返回一个Object^,因此,要把它转换成D^类型。当原始及克隆的代理在标号6c、6d中调用时,结果输出如下:

Object t1: 5
Object t2: 5
Object t1: 6
Object t2: 6

  关于函数ProcessList,如果参数中的代理实例为nullptr,即没有调用列表,那它将直接返回;如果排除的对象为nullptr,那么列表中所有的函数都将被调用;如果存在要排除的对象,就要像标号8中那样把调用列表当作代理数组取出,接着,在标号9中逐个排查不相符的入口,最后,在标号10中调用余下的这些函数。尽管在调用列表中每个入口都是Del类型,但GetInvocationList返回一个基类Delegate数组,所以在调用每个代理实例之前,需像标号10那样先转换成类型D。

  事件

  在C++/CLI中,事件是一种当某种重要事情发生时,为客户程序提供通知的机制。鼠标单击就是事件的一个典型例子,在事件发生之前,有关的客户程序必须先注册它们感兴趣的事件,如,当检测到鼠标单击时,这些程序就会接到通知。

  通过添加或删除一个或多个感兴趣的事件,事件列表可在运行时增长或缩减,请看例7中Server类型的定义,在标号1中,Server类定义了代理类型NewMsgEventHandler(一般约定在用于事件处理时,代理类型添加EventHandler的后缀名),接着,在标号2中,定义了一个名为ProcessNewMsg的公共事件(event在此为一个上下文关键字)。一个事件必须有一个代理类型,实际上,像这样的一个事件已经是一个代理实例了,而且因为它被默认初始化为nullptr,所以它没有调用列表。

  例7:

using namespace System;

public ref struct Server
{
 /*1*/ delegate void NewMsgEventHandler(String^ msg);
 /*2*/ static event NewMsgEventHandler^ ProcessNewMsg;
 /*3*/ static void Broadcast(String^ msg)
 {
  if (ProcessNewMsg != nullptr)
  {
   ProcessNewMsg(msg);
  }
 }
};

  当通过一条消息调用时,函数Broadcast将调用包装在ProcessNewMsg调用列表中所有的函数。

  Client类定义在例8中,一个Client的类型实例无论何时被创建,它都会通过向为Server::ProcessNewMsg维护的代理列表中添加一个实例函数(它关联到实例变量),来注册它所感兴趣的新Server消息,而这是通过 += 操作符来完成,如标号5中所示。只要这个入口一直保持在通知列表中,无论何时一个新消息送达Server,注册的函数都会被调用。

  例8:

using namespace System;
public ref class Client
{
 String^ clientName;
 /*4*/ void ProcessNewMsg(String^ msg)
 {
  Console::WriteLine("Client {0} received message {1}", clientName, msg);
 }
 public:
  Client(String^ clientName)
  {
   this->clientName = clientName;
   /*5*/ Server::ProcessNewMsg += gcnew Server::NewMsgEventHandler(this, &Client::ProcessNewMsg);
  }
  /*6*/ ~Client()
  {
   Server::ProcessNewMsg -= gcnew Server::NewMsgEventHandler(this, &Client::ProcessNewMsg);
  }
};

  要从通知列表中移除一个入口,可使用 -= 操作符,如标号6定义的析构函数中那样。
天极yesky

上一页  [1] [2] [3] [4] [5]  下一页

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:31,328.13000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号