2

有谁知道框架,最好是让 Flex 编译器运行扩展的某种方式,或者可能只是一个构建步骤,我们可以生成应用程序数据模型的强类型代理类。

我们想要对代理做两件主要的事情:

  1. 在运行时,我们希望延迟解析和实例化访问的实例(类似于 Java 的 Hibernate 具有延迟代理对象的方式)
  2. 在编辑器应用程序中,我们希望实现 setter 调用,以便我们可以跟踪哪些对象已被修改
    • 在这种情况下,除了以编程方式设置 ChangeWatcther 之外,Proxy 确实是必要的,因为我们需要跟踪数组添加/删除并可能跟踪“引用”对象,以便当“引用键”发生更改时,我们知道保存那些正在引用的对象按键

在第一种情况下,我们希望代理在从序列化数据中加载该对象时基本上抽象,但如果它是真实对象,仍然使用相同的公共属性和数据访问模式传递它的引用。

基本上,代理将在第一次对其调用方法时实例化该对象。

我知道我们可以使用一些 AS3 字节码库,例如as3-commons-bytecode

或者可能重新利用 GraniteDS 代码生成。

我更喜欢生成代码,因为它是一个确定性的东西,如果我们有办法在运行时更容易地调试它,那就太好了。

有谁知道当它从 MXML 文件生成 AS3 代码时我是否可以做类似 MXMLC 的事情。

还有无论如何控制编译管道中的“何时”我可以生成代码,因为我们有很多使用公共字段而不是getter / setter的数据对象,但那是[Bindable],所以如果我可以生成基于代理在生成的 getter/setter 方法上会起作用。

这是一个示例应用程序数据对象和代理类:

[Bindable]
public class PersonDTO implements Serializable {
    private var _name:String;

    private var _age:Number


    public function get age():Number {
        return _age;
    }

    public function set age(a:Number):void {
        _age = a;
    }

    public function get name():String {
        return _name;
    }

    public function set name(n:String):void {
        _name = n;
    }

    public void readObject(data:*) {
        //...
    }

}

// GENERATED CLASS BASED ON PersonDTO
public class LazyProxy_PersonDTO extends PersonDTO {

    private var _instance:PersonDTO = null;
    private var _instanceData:*;

    private function getInstance():void {
        if (_instance == null) {
            _instance = new PersonDTO();
            _instance.readObject(_instanceData);
        }
    }

    override public function get age():Number {
        //Ensure object is instantiated
        return getInstance().age;
    }

    override public function get name():String {
        //Ensure object is instantiated
        return getInstance().name;
    }

}

// GENERATED CLASS BASED ON PersonDTO
public class LogChangeProxy_PersonDTO extends PersonDTO {

    //This will be set in the application
    public var instance:PersonDTO;

    //set by application
    public var dirtyWatcher:DirtyWatcherManager;

    override public function set age(a:Number):void {
        dirtyWatcher.markAsDirty(instance);
        instance.age = a;
    }

}
4

1 回答 1

2

深入挖掘 AS3-Commons 字节码库,看起来它们支持生成代理类和拦截器。

  • http://www.as3commons.org/as3-commons-bytecode/proxy.html

    public class DirtyUpdateInterceptor implements IInterceptor {
    
    public function DirtyUpdateInterceptor() {
        super();
    }
    
    public function intercept(invocation:IMethodInvocation):void {
        if (invocation.kind === MethodInvocationKind.SETTER) {
            if (invocation.arguments[0] != invocation.instance[invocation.targetMember]) {
                invocation.instance.isDirty = true;
            }
        }
    }
    }
    
于 2011-11-22T17:54:39.870 回答