用于延迟实例化的 Flex 强类型代理类

发布于 2024-12-17 14:14:11 字数 2404 浏览 1 评论 0原文

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

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

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

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

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

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

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

我更喜欢生成代码,因为它是确定性的事情,如果我们能够有一种在运行时更轻松地调试它的方法,那就太好了。

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

还有无论如何可以控制编译管道中的“何时”我可以生成代码,因为我们有很多使用公共字段而不是 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;
    }

}

Does anyone know of a framework, preferably some way to have the Flex compiler run an extension or perhaps just a build step that we could generate strongly typed proxy classes of our application's data models.

There are 2 main things we want to do with the proxy's:

  1. At runtime we want to lazily parse and instantiate the instance as accessed (similiar to how Java's Hibernate has Lazy proxy objects)
  2. In an editor application we want to implement setter calls so we can track which objects have been modified
    • The Proxy is really necessary in this situation beyond things like programatically setting up ChangeWatcther's because we need to track Array adds/remove and possibly track "reference" objects so that when a "reference key" is changed we know to save those objects that are referencing it by key

In the first case we want the proxy to basically abstract when that object is loaded from serialized data, but still pass around references of it with the same public properties and data access pattern if it were the real object.

Basically the proxy would instantiate the object the first time a method is called on it.

I know we could use some AS3 byte-code libraries like as3-commons-bytecode.

Or possibly repurposing the GraniteDS Code Generation.

I'd prefer to generate code because it is a deterministic thing and it'd be nice if we could have a way to debug it at runtime easier.

Does anyone know if I could do something like MXMLC does when it generates AS3 code from MXML files.

Also is there anyway to control "when" in the compilation pipeline I can generate code, because we have a lot of data objects using public fields instead of getter/setters, but that are [Bindable] and so if I could generate the proxy based on the generated getter/setter methods that would work.

Here's an example application data object and proxy classes:

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

猥琐帝 2024-12-24 14:14:11

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

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

    公共类 DirtyUpdateInterceptor 实现 IInterceptor {
    
    公共函数 DirtyUpdateInterceptor() {
        极好的();
    }
    
    公共函数拦截(调用:IMethodInitation):void {
        if (incalling.kind === MethodInitationKind.SETTER) {
            if (invoking.arguments[0] != invoking.instance[invoking.targetMember]) {
                incalling.instance.isDirty = true;
            }
        }
    }
    }
    

Digging a little deeper into AS3-Commons byte code library it looks like they support generating proxy classes and interceptors.

  • 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;
            }
        }
    }
    }
    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文