【问题标题】:Actionscript Compiler directiveActionscript 编译器指令
【发布时间】:2011-09-28 16:13:23
【问题描述】:

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

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

【问题讨论】:

    标签: apache-flex actionscript flex4 mate


    【解决方案1】:

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

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

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

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

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

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

    编译器的源代码可在此处获得。查看Managed extension 的代码作为一个很好的起点可能是值得的。

    或者,看看SkinPart 扩展、HostComponent 扩展或 [Embed](Clement Wong - 编译器的原始开发人员 - 曾提到这是理解编译器扩展的最佳起点)。

    【讨论】:

    • 这个托管元标记很有趣,我试试看,谢谢。
    【解决方案2】:

    我想你想使用keep--as3-metadata compiler argument。像这样的:

    keep-as3-metadata+=LazyLoaded

    【讨论】:

    • 我想用延迟加载的方法替换公共 var,类似于在编译时将 [Bindable] var 替换为它的 getter/setter。
    • 哦,唯一要做的就是将您的元数据保存在已编译的 SWC 中。大多数框架创建者在运行时根据他们的自定义元数据执行此类操作。有一种方法可以深入到组件中以查找元数据和其他信息。如果您想更改 Flex 编译器的工作方式,以便基于该元数据生成不同的代码,您将不得不更改 Flex 编译器。这是可行的,因为您可以获得源代码。不过,我认为它不实用。
    • 谢谢,我希望它有某种“钩子”,但我明白你在说什么,这个应用程序需要进行预编译,而不是运行时。
    • @SuperSaiyen 你最好使用一些 ANT 脚本或其他可以解析代码、查找元数据并在编译之前进行适当转换的构建工具。
    【解决方案3】:

    +1 Marty 你把我带到了这个,但它与你的解决方案不同。

    我创建了一个所有其他 Mate 数据管理器都可以扩展的基类 (BaseDataManager),并且在该类中我添加了以下代码:

            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;
        }
    

    通过这种方式,大部分丑陋、难以阅读的代码都隐藏在开发人员之外,但如果出现任何问题,仍然可以进行调试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-24
      • 1970-01-01
      • 2018-05-26
      • 1970-01-01
      • 1970-01-01
      • 2017-01-07
      • 1970-01-01
      • 2012-01-06
      相关资源
      最近更新 更多