我有一个通过AMF从服务器延迟加载数据的既定模式。
private var _XeventDispatched:Boolean;
private var _X:ArrayCollection;
public function get X():ArrayCollection{
if(!_XeventDispatched && (_X==null || _X.length==0)){
var evt:Event = new Event();//whatever event is need for this data member
dispatcher.dispatchEvent(evt);
_XeventDispatched = true;
}
return _X;
}
public function set X(ac:ArrayCollection):void{
return _X;
}
这样,直到需要时才从服务器加载数据。(顺便说一下,我使用的是Mate框架,所以当一个UI被实例化时,注入器会触发,它们会调用数据管理器类中的这个get方法。)
我想做的是创建某种元数据标签,类似于[Bindable],它将添加上述方法来代替公共属性。
[LazyLoaded(eventName="com.myCompany.LoadX")]
public var X:ArrayCollection;
编译器对这种类型的扩展有钩子吗?这将节省大量难以阅读的样板代码。
正如Flextra所提到的,一种选择是使用元数据的运行时反射,并以此为基础构建框架。
这类似于延迟加载在phiberate(我是一个开发人员的Flex延迟加载框架)中的实现方式。特别是为了访问getter和setter,并使用钩子拦截它们进行延迟加载,我们使用[Managed]
元标签,并调整它的行为,这使得编译器为你构建钩子。
这是一个小技巧,但它可能会帮助你。(我们在此基础上构建了一个非常成功的框架)。
或者,您可以编写自己的编译器扩展,使用您的元数据,并执行AST修改来为您生成代码。但是,它不适合胆小的人。
尽管这些扩展的钩子已经存在很多年了,但是很少有关于如何实现它的,你需要通过查看现有的源代码来解决它。
幸运的是,Adobe的研究人员在编译器扩展方面一直在吃自己的狗肉,并且Flex 4的一些特性(如皮肤)已经被实现为编译器扩展,给了你更多的例子来工作。
编译器的源代码可以在这里找到。作为一个良好的起点,看一看托管扩展的代码可能是值得的。
或者,看看SkinPart扩展,HostComponent扩展或[Embed] (Clement Wong -编译器的原始开发人员-曾经提到过作为理解编译器扩展的最佳起点)。
我认为您想使用keep——as3-metadata编译器参数。像这样:
keep-as3-metadata + = LazyLoaded
+1马蒂,是你让我这么做的,但这与你的解决方案不同。
我已经创建了一个基类(BaseDataManager
),所有其他Mate数据管理器都可以从它扩展,并在该类中添加了以下代码:
private var eventsDispatched:Array = new Array();
protected function lazyLoad(value:*, eventType:String):*{
if(!eventsDispatched[event] && (value==null || (value is IList && IList(value).length==0))){
var clazzName:String = eventType.substr(0, eventType.indexOf(":"));
var eventClazz:Class = Class(getDefinitionByName(clazzName));
var event:Event = new eventClazz(eventType);
dispatcher.dispatchEvent(event);
eventsDispatched[event] = true;
}
return value;
}
然后在每个数据管理器中,如果属性是延迟加载的,这是它们的访问器:
private var _X:ArrayCollection;
public function get X():ArrayCollection{
return lazyLoad(_X, XLoadEvent.LOAD_EVENT_TYPE);
}
public function set X(value:ArrayCollection):void{
_X = value;
}
通过这种方式,大多数难看的、难以阅读的代码对开发人员隐藏起来,但如果出现任何问题,仍然可以进行调试。