Гибкие строго типизированные прокси-классы для ленивых экземпляров - PullRequest
2 голосов
/ 22 ноября 2011

Кто-нибудь знает каркас, желательно какой-нибудь способ заставить компилятор Flex запустить расширение или, возможно, просто шаг сборки, чтобы мы могли генерировать прокси-классы со строгой типизацией для моделей данных нашего приложения.

Существует 2Основные вещи, которые мы хотим сделать с прокси:

  1. Во время выполнения мы хотим лениво проанализировать и создать экземпляр экземпляра как доступный (аналогично тому, как в Hibernate Java есть прокси-объекты Lazy)
  2. Вприложение редактора, которое мы хотим реализовать вызовами установщика, чтобы мы могли отслеживать, какие объекты были изменены
    • Прокси действительно необходим в этой ситуации, помимо таких вещей, как программная настройка ChangeWatcther, потому что нам нужно отслеживать добавление / удаление массива и, возможно,отслеживать «ссылочные» объекты, чтобы при изменении «ссылочного ключа» мы знали, как сохранить те объекты, которые ссылаются на него по ключу

В первом случае нам нужен проксив основном абстрагироваться, когда этот объект загружается из сериализованногоданные, но по-прежнему передают ссылки на них с теми же общедоступными свойствами и шаблоном доступа к данным, если бы это был реальный объект.

По сути, прокси создает экземпляр объекта при первом вызове метода для него.

Я знаю, что мы могли бы использовать некоторые библиотеки байт-кода AS3, такие как as3-commons-bytecode .

Или, возможно, изменить использование кода GraniteDS.

I 'я бы предпочел генерировать код, потому что это детерминированная вещь, и было бы неплохо, если бы у нас был способ отладить его во время выполнения.

Кто-нибудь знает, могу ли я сделать что-то подобное, что делает MXMLC, когда он генерируетКод AS3 из файлов MXML.

Также в любом случае есть возможность контролировать «когда» в конвейере компиляции, я могу генерировать код, потому что у нас много объектов данных, использующих открытые поля вместо getter / setters, но это [Bindable], и ​​поэтому, еслиЯ мог бы сгенерировать прокси на основе сгенерированных методов получения / установки, которые будут работать.

Вот пример объекта данных приложения и прокси-классов:

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

}

1 Ответ

2 голосов
/ 22 ноября 2011

Углубившись немного глубже в библиотеку байтового кода 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;
            }
        }
    }
    }
    
...