2

我有一个通过 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;

编译器对这种类型的扩展有任何钩子吗?它将节省大量难以阅读的样板代码。

4

3 回答 3

2

正如 Flextra 所提到的,一种选择是使用元数据的运行时反射,并围绕它构建您的框架。

这类似于延迟加载在 dpHibernate(我是开发人员的 Flex 延迟加载框架)中实现的方式。特别是为了访问 getter 和 setter 并使用钩子拦截它们以进行延迟加载,我们使用[Managed]元标记,并调整它的行为,让编译器为您构建钩子。

这有点像黑客,但它可能会对你有所帮助。(我们已经在这个 hack 之上构建了一个非常成功的框架)。

或者,您可以编写自己的编译器扩展,使用您的元数据,并执行 AST 修改来为您生成该代码。但是,它不适合胆小的人。

尽管这些扩展的钩子已经存在很多年了,但是关于如何做的却很少,你需要通过查看现有的源来解决它。

幸运的是,Adobe 的研究人员在编译器扩展方面一直在吃他们自己的狗粮,并且 Flex 4 的一些功能(例如 Skinning)已作为编译器扩展实现,为您提供了更多示例。

编译器的源代码可在此处获得。将托管扩展的代码作为一个很好的起点可能会有所帮助。

或者,查看SkinPart扩展、HostComponent扩展或 [ Embed ](Clement Wong - 编译器的原始开发者 - 曾将其作为理解编译器扩展的最佳起点)。

于 2011-09-29T22:01:03.250 回答
0

我认为您想使用keep--as3-metadata 编译器参数。像这样的东西:

keep-as3-metadata+=LazyLoaded

于 2011-09-28T16:22:15.260 回答
0

+1 Marty,您将我引向此,但它与您的解决方案不同。

我创建了一个基类 ( 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;
    }

这样,大多数丑陋、难以阅读的代码都被隐藏在开发人员之外,但如果出现任何问题,仍然可以进行调试。

于 2011-09-30T14:08:15.793 回答