适合C# Actor的消息执行方式(6):协变与逆变
2010-09-30 20:50:09 来源:WEB开发网Monitor的具体实现和上篇文章区别不大,您可以参考文章末尾给出的完整代码,并配合前文的分析来理解,这里我们只关注被标红的两行代码。
在第一行中我们创建了一个Crawler类型的对象,并把它赋值给IPort<ICrawlerRequestHandler>类型的变量中。请注意,Crawler对象并没有实现这个接口,它只是实现了IPort<Crawler>及ICrawlerRequestHandler。不过由于IPort<T>支持协变,于是IPort<Crawler>被安全地转换成了IPort<ICrawlerRequestHandler>对象。
第二行中再次发生了协变:ICrawlRequestHandler.Crawel的第一个参数需要IPort<ICrawlResponseHandler>类型的对象,但是this是Monitor类型的,它并没有实现这个接口。不过,和上面描述的一样,由于IPort<T>支持协变,因此这样的类型转化是安全的,允许的。于是在Crawler类便可以操作一个“抽象”,而不是具体的Monitor类型来办事了。
神奇不?但就是这么简单。
“内部”消息控制
在上一篇文章中,我们还提出了Crawler实现的另一个缺点:没有使用异步IO。WebClient本身的DownloadStringAsync方法可以进行异步下载,但是如果在异步完成的后续操作(如分析链接)会在IO线程池中运行,这样我们就很难对任务所分配的运算能力进行控制。我们当时提出,可以把后续操作作为消息发送给Crawler本身,也就是进行“内部”消息控制——可惜的是,我们当时无法做到。不过现在,由于Crawler实现的是IPort<Crawler>接口,因此,我们可以把Crawler内部的任何方法作为消息传递给自身,如下:
internal class Crawler : Actor<Action<Crawler>>, IPort<Crawler>, ICrawlRequestHandler
{
protected override void Receive(Action<Crawler> message) { message(this); }
#region ICrawlRequestHandler Members
public void Crawl(IPort<ICrawlResponseHandler> collector, string url)
{
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error == null)
{
this.Post(c => c.Crawled(collector, url, e.Result));
}
else
{
collector.Post(c => c.Failed(this, url, e.Error));
}
};
client.DownloadStringAsync(new Uri(url));
}
private void Crawled(IPort<ICrawlResponseHandler> collector, string url, string content)
{
var matches = Regex.Matches(content, @"href=""(http://[^""]+)""").Cast<Match>();
var links = matches.Select(m => m.Groups[1].Value).Distinct().ToList();
collector.Post(c => c.Succeeded(this, url, content, links));
}
#endregion
}
- ››适合做商品团购营销的网站
- ››适合所有浏览器hack的CSS技巧
- ››消息称中国移动即将获得iPhone 4销售权
- ››适合C# Actor的消息执行方式(1):Erlang中的模式...
- ››适合C# Actor的消息执行方式(2):C# Actor的尴尬...
- ››适合C# Actor的消息执行方式(3):中看不中用的解...
- ››适合C# Actor的消息执行方式(4):阶段性总结
- ››适合C# Actor的消息执行方式(5):一个简单的网络...
- ››适合C# Actor的消息执行方式(6):协变与逆变
- ››适合1-5个月经验的seo优化全过程分享
- ››消息称联通高层赴美谈引入iPhone4 将带WiFi
- ››消息称微软将在近期发布IE9 beta
更多精彩
赞助商链接