你的分享就是我们的动力 ---﹥

Silverlight应用程序的本地通讯

时间:2011-10-08 09:55来源:www.chengxuyuans.com 点击:

在实际开发中,可能会在同一个网页上放置多个Silverlight应用程序,而这些应用程序之间可能需要 互相通讯,比如实现两个Silverlight应用程序之间的同步。

从Silverlight 3开始,我们可以使用“System.Windows.Messaging”命名空间中的两个类—— LocalMessageSender和LocalMessageReceiver,在运行于同一台计算机上的两个Silverlight应用程序间 相互交换信息。

顾名思义,LocalMessageSender类用于发送消息,而LocalMessageReceiver则用于接收消息。

当一个Silverlight应用程序需要发送消息时,实例化一个LocalMessageSender对象,类似地,如果它 需要接收消息,实例化一个LocalMessageReceiver对象。

消息发送与接收的“配对”关系通过消息接收者的“域名+接收对象名字”来确定。只要“域名+接收 对象名字”一致,多个LocalMessageSender对象就可以向同一个LocalMessageReceiver对象发送消息。

了解了上述知识,开发能相互通讯的Silverlight应用程序就有了章法。

请看文后所附之示例解决方案LocalCommunication。

图1 在同一个网页上相互通讯的Silverlight程序

如图1所示,示例解决方案LocalCommunication在同一个ASP.NET网页上承载了两个Silverlight应用程 序。用户在发送端应用程序输入一个消息字串,并从下拉框中选择一个命令(“椭圆”或“矩形”)之后 ,发送端应用程序会将这两个信息以“;”作为间隔符组合成一个复合信息发送出去。

接收端应用程序在收到信息之后,解析收到的信息,将字串显示出来,并依据接收到命令显示一个“ 椭圆”或“矩形”。

下面剖析一下示例程序,以帮助大家掌握相关的技术要点。

1 消息发送方

在发送端示例程序,需要实例化一个LocalMessageSender对象:

LocalMessageSender Sender = new LocalMessageSender(
                     "LocalCommunication.Receiver");

特别注意一下构造函数中的参数指定了接收者的名字。此名字将用于定义消息的接收者。

实例化LocalMessageSender对象之后,就可以调用其SendAsync()方法“异步”发送信息:

Sender.SendAsync("要发送的信息");

如果需要接收消息接收方发回的“消息已接收”通知,通常会给LocalMessageSender对象的 SendCompleted方法挂接一个事件响应函数,在此函数中可以通过其参数e(类型为 SendCompletedEventArgs)的Response属性获取用户发回的“回执”。

Sender.SendCompleted += new
         EventHandler<SendCompletedEventArgs> (Sender_SendCompleted);

2 消息接收方

类似地,消息接收方示例程序实例化一个LocalMessageReceiver对象,注意其名字一定要与消息发送 方一致。

LocalMessageReceiver Receiver = new
         LocalMessageReceiver("LocalCommunication.Receiver");

然后,为其挂接事件响应函数,在此函数中处理接收到的消息。

Receiver.MessageReceived += new 
         EventHandler<MessageReceivedEventArgs> (Receiver_MessageReceived);

从事件参数e(其类型为MessageReceivedEventArgs)的Message属性可以读取发送方传过来的消息。

最后,调用Listen()方法监听消息:

Receiver.Listen();

最关键的地方就是这么多了。是不是很简单?

但还是有一些东西需要交代的。

(1)在消息发送方,LocalMessageSender对象有一个ReceiverDomain属性,默认值为null,这意味着 ,消息的发送方与接收方必须位于同一个域(Domain)中。

注意:

“域(Domain)”和“应用程序域(AppDomain)” 不是一回事。域表明了Silverlight应用程序的位 置信息,诸如:“www.myuniversity.edu.cn”之类,而应用程序域则代表了 Silverlight应用程序的运 行环境,Silverlight插件在装载一个Silverlight应用程序时,会为其创建一个应用程序域作为其运行环 境。

假设某网页使用多个<object>元素承载了多个Silverlight应用程序,则Silverlight插件会为 每个 Silverlight应用程序创建相互独立的应用程序域,这些Silverlight应用程序的“域”可以相同( 只要来源于同一个网站),也可以不同(如果来源于不同的网站)。

如果将发送方的ReceiverDomain属性设置为LocalMessageSender.Global值(其实就是一个仅包容单个 “*”字符的字串),则发送方可以向另一个域的Silverlight应用程序发送信息。

(2)在消息接收方,LocalMessageReceiver对象的名字决定了其是否能接收到消息。因此,在同一个 域中绝对不要创建拥有相同名字的LocalMessageReceiver对象!

如果你硬要这么做,当调用LocalMessageReceiver.Listen()方法开始监听时,你会得到一个 ListenFailedException,不能接收消息。

为了处理“名字”问题,LocalMessageReceiver类提供了一个NameScope属性,其默认值为 “ReceiverNameScope.Domain”,表示这个名字必须在当前域中唯一。它的另一个可选值是 “ReceiverNameScope.Global”,表示在当前计算机上运行的所有Silverlight应用程序所涉及到的域中 ,这个名字都必须是独一无二的。

“ReceiverNameScope.Global”值是一个非常强的约束条件,你可以保证在“自己的”域中名字唯一 ,但你无法保证来源于其他网站的Silverlight应用程序在给LocalMessageReceiver对象取名时一定不会 与你“英雄所见略同”。

为了解决这一问题,笔者的建议是给LocalMessageReceiver对象的名字中加上一个GUID值,这样,同 名的机会就很少了。

另外,还要注意消息接收方与消息发送方的设置必须一致,比如消息发送方的ReceiverDomain属性设 置为“LocalMessageSender.Global”,则接收方的NameScope属性也必须设置为 “ReceiverNameScope.Global”。

(3)由于消息接收方可能会接收多个消息发送方发来的消息,因此有可能某个“不速之客”(指某个 在本机上加载的Silverlight应用程序)“恰巧”地“蒙”对了消息接收对象的名字,这将导致消息接收 方应用程序可能会接收到“非法”的,有可能是“恶意”的指令,因此,LocalMessageReceiver类还设计 了另一个AllowedSenderDomains属性来限制可以发送消息的域,这个属性是一个“有资格发送消息的” Silverlight应用程序所在域名字串的集合:

public IEnumerable<string> AllowedSenderDomains { get; }

域名不在此集合范围内的Silverlight应用程序发送的消息,将被接收方所拒绝。

可以使用LocalMessageReceiver的另一个构造函数一次性地为上述介绍过的属性进行赋值:

Receiver = new LocalMessageReceiver("LocalCommunication.Receiver",
         ReceiverNameScope.Global,
         new string[] {"www.myFriend.com","www.myHost.com"});

上述代码指定只有来自于“www.myFriend.com”和“www.myHost.com”的Silverlight应用程序可以“ 跨域”向“我”发送信息。

如果允许接收任何一个域的消息,可以将AllowedSenderDomains属性设置为 “LocalMessageReceiver.AnyDomain”值,此值引用仅包容了一个“*”字串的数组对象。

再次警告,这是个“危险”的值,使用时要慎重!

另外,属于同一域内的多个Silverlight应用程序间通讯总是许可的。

(4)如果允许Silverlight应用程序脱离浏览器运行,那么,默认情况下运行于浏览器中的 Silverlight应用程序是不能与浏览器外的“兄弟”通讯的。如果需要启用这个功能,必须在创建 LocalMessageReceiver对象时,将其DisableSenderTrustCheck属性设置为true(其默认值为 false):

Receiver.DisableSenderTrustCheck = true;

下面做个小结:

可以使用LocalMessageSender和LocalMessageReceiver方便地在运行于同一台计算机上的多个 Silverlight应用程序间相互通讯,其中的关键在于要正确地匹配名字和给相关的属性赋与有效的值。

在实际开发中,要特别注意安全性问题。

此外,每次能传送的信息大小是有限制的,最大上限为40K。信息的格式是由程序员决定的,由于 Silverlight对序列化XML和JSON格式的数据提供了支持,因此,使用它们会比较方便,只要注意消息大小 别越限就好了。

随文源码

转载注明地址:http://www.chengxuyuans.com/slverlight/21807.html