.NET 时代的面向方面的程序设计
这里有许多映射两个构件的方法,其中一个是使用带有数据的XML文件,另一个就是把这些映射放到数据库中。然而,两者(其它也是一样)有一些非常重要的缺点。
• 映射文件/储存成为可维护性的另一方面。普通
• 映射的下载和解析成为一个高负荷的问题
• 与一般的拖曳&拖曳-控制-设置-属性-运行开发模式有很大的背离
避免这些问题的一个方法就是扩展嵌入式控件,实现控件自己的映射设置。仅仅数出嵌入式Web 和Windows窗体控件的数量就是一项艰巨的工作外,映射功能中的任何改变将要求对控件代码作出修改,可是这好像不是一个好办法。除了这些,可能我们不能继承第三方已经获得的控件。
VS.NET支持一个扩展器的概念,扩展器的概念是一个构件,它扩展来自于外部的现有构件的功能集,既不要求继承,也不要求内含包容,或者甚至会访问被扩展构件的任何内部信息。这个扩展性模式通常被称为面向方面程序设计,因为它允许我们简单地增加,并且从外面将方面移出到现有构件。这种技术有它自己的网页,网络上可能有很多关于它的文章。在MSDN上可以找到与此主题相关的一篇有趣的文章,尽管它的方法接受自定义属性的途径。
面向方面的程序设计的组件方法是System.ComponentModel命名空间里的IExtenderProvider接口和ProvidePropertyAttribute类型。这个属性必须被应用到构件,此构件将扩展其它构件。
[ProvideProperty("WebViewMapping", typeof(System.Web.UI.Control))]
public class BaseController : Component, IExtenderProvider
这个属性对VS.NET所说的就是:构件(Base控制器)给根组件 (一个Web 窗体)里的类型System.Web.UI.Control 的所有构件提供一个属性WebViewMapping。我们可以提炼控件:bool IExtenderProvider.CanExtend(object extendee)我们总是说支持Control-继承对象(在这个层,早已传递了ProvideProperty过滤器)。对于根组件,映射没有什么意义,也就是说,Page对象它自己是从Control继承而来的。正如我们在开始所谈到的,为了证明这个情况,我们可以利用IDesignerHost服务,通过调用GetService方法,我们可以从构件直接访问IDesignerHost服务,正如在开始所讨论的一样。
{
return true;
}
bool IExtenderProvider.CanExtend(object extendee)GetService的Component类型的实现简单地向Component.Site属性值对象发出了要求,此要求就是DesignSite,DesignSite包含几个其它服务。
{
//Retrieve the service.
IDesignerHost host = (IDesignerHost) GetService(typeof(IDesignerHost));
//Never allow mappings at the root component level (Page or Form).
if (extendee == host.RootComponent)
{
return false;
}
else
{
return true;
}
}
为了使它能够有效工作,必须实现接口和属性,意识到这一点非常重要。最后的部分就是大量附带有特殊命名惯例的方法,这些方法必须存在在扩展器构件中。
/// <summary>
/// Gets/Sets the view mapping that is used with the control.
/// </summary>
[Category("ClariuS MVC")]
[Description("Gets/Sets the view mapping that is used with the control.")]
public string GetWebViewMapping(object target)
{
//Retrieve a mapping
}
/// <summary>
/// Sets the mapping that applies to this control.
/// </summary>
public void SetWebViewMapping(object target, string value)
{
//Store the mapping
}