如何在 CLR 类型上实现 IronPython 语言的动态特性,简单的讲,可以通过 ICustomAttributes 接口来实现。
ICustomAttributes 接口是在 IronPython 引擎中定义的 。其成员是给 CLR 类型附加自定义属性的一些操作,一旦定义了这些附加的属性,IronPython 的脚本就通过引擎来访问它们。需要注意的是,这里所谓的属性是 Python 概念中的 attribute,它可以是 Python 函数,类,变量等。
public interface ICustomAttributes {
void DeleteAttr(ICallerContext context, SymbolId name);
IDictionary < object , object > GetAttrDict(ICallerContext context);
List GetAttrNames(ICallerContext context);
void SetAttr(ICallerContext context, SymbolId name, object value);
bool TryGetAttr(ICallerContext context, SymbolId name, out object value);
}
}
在 IronPython for ASP.NET 中定义了三个类:ScriptUserControl, ScriptPage, ScriptMaster. 分别用于页面、用户控件、和母版页。研究了它们的实现后,我画了下面一张图描述其实现情况:
首先,这几个类分别继承自 ASP.NET 中原先的基类。即 System.Web.UI 名称空间下的 Page, UserControl 以及 MasterPage. 在继承了基类特性的同时,它们都实现了 ICustomAttributes 接口。
而在这几个类的内部,ICustomAttributes 接口是通过其成员 ScriptTemplateControl 来实现的,这里是一个桥接模式(Bridge Pattern)。因此,ScriptTemplateControl 才是真正的实现者,在 ScriptTemplateControl 中,实现了自动读取、分析页面相关的后台代码或内联代码,并关联相关的事件处理函数(Event Handlers),以及调用一般函数和数据绑定函数等许多重要的功能,在后续的文章中我会详细来分析其中的一些实现。