Проблема внедрения зависимости Parsley в Flex 4 с использованием шаблона Presentation Model

У меня есть класс представления EmployeeList следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<s:NavigatorContent xmlns:fx="http://ns.adobe.com/mxml/2009" 
                    xmlns:s="library://ns.adobe.com/flex/spark"
                    xmlns:parsley="http://www.spicefactory.org/parsley"
                    xmlns:mx="library://ns.adobe.com/flex/mx" width="400" height="300">


    <fx:Script>
        <![CDATA[
            import cafeparsley.model.EmployeeListPM;

            [Inject]
            [Bindable]
            public var model : EmployeeListPM;

            [Init]
            public function init () : void {
                model.init();
            }


        ]]>
    </fx:Script>    

    <s:Panel title="Employee List" horizontalCenter="0">
        <s:HGroup paddingTop="50">
            <s:Button label="Add New Employee" click="model.addNewEmployee()" />
            <mx:Spacer width="100%" />
            <s:Button label="Logout" click="model.logout()" />
            <mx:Spacer width="100%" height="20" />  
        </s:HGroup>
        <s:List id="empList" dataProvider="{ model.employees }" labelFunction="model.properName" 
                 change="model.initUpdateEmployee(empList.selectedItem);empList.selectedIndex = -1;" width="100%" />
        <s:Label id="error" color="0xFF0000" />
    </s:Panel>  

</s:NavigatorContent>

ПМ выглядит так:

package cafeparsley.model
{
    import cafeparsley.events.EmployeeEvent;
    import cafeparsley.events.NavigationEvent;
    import cafeparsley.services.impl.EmployeeServiceImpl;
    import cafeparsley.vo.Employee;

    import flash.events.EventDispatcher;

    import mx.collections.ArrayCollection;
    import mx.rpc.IResponder;

    [Bindable]
    [Event(name="navigationEvent", type="cafeparsley.events.NavigationEvent")]
    [ManagedEvents("navigationEvent")]
    public class EmployeeListPM extends EventDispatcher implements IResponder
    {

        public var employeeService : EmployeeServiceImpl = new EmployeeServiceImpl();

        public var employees : ArrayCollection;

        public function init() : void
        {
            loadEmployees();
        }


        public function EmployeeListPM() 
        {
        }

        public function loadEmployees():void
        {
            employeeService.loadEmployees( this );
        }  

Независимо от того, использую ли я для выполнения инъекции или выполняю автоматическое подключение, когда я запускаю это, я получаю следующее сообщение об ошибке:

Таким образом, employeeListPM имеет значение null, когда возникает ошибка. Однако, если я закомментирую компонент <s:List>, перезапущу и установлю точку останова в методе init, будет вызвана функция init (). Так что дело не в том, что моя конфигурация контекста неверна, просто PM не был введен вовремя и выдается ошибка. Но согласно руководству Parsley, если я использую автоматическое подключение или <parsley:configure/>, PM должен быть введен к тому времени, когда это необходимо.

Я не понимаю, что я делаю неправильно в том, что я считал относительно тривиальным сценарием внедрения зависимостей. Вы можете помочь?

Здесь пара моментов:


person Murray    schedule 08.09.2011    source источник


Ответы (2)


В вашем примере нет тегов <Configure /> или <FastInject />, однако, поскольку вы упоминаете их в своем сообщении, я предполагаю, что они просто отсутствуют в образце кода. (В противном случае вам нужно добавить один из них, чтобы это работало).

Однако более вероятно, что в вашем коде есть условия гонки.

В частности, эти строки:

Model - это внедренное свойство, однако не гарантируется, что оно было внедрено во время первого запуска кода.

labelFunction="model.properName" 
change="model.initUpdateEmployee(empList.selectedItem);empList.selectedIndex = -1;"

Вместо этого переместите код в сценарий внутри класса, который выполняет нулевую проверку, а затем передает логику обратно менеджеру.

Также следует учитывать, что вы вызываете model.init () из функции View, отмеченной метатегом Parsley [Init]. Я бы посоветовал вам применить тот же метатег [Init] к методу init () модели.

ie:

labelFunction="nameFunction"


private function nameFunction(item:Object):String
{
    return (model) ? model.properName(item) : "";
}
person Marty Pitt    schedule 08.09.2011

Сделайте это вместо того, чтобы вызывать model.init () из представления. В документации по жизненному циклу говорится:

[Init]    
public function loadEmployees():void {
     employeeService.loadEmployees( this );
}

Методы, отмеченные [Init], вызываются после того, как объект был создан и все инъекции были обработаны.

У меня были гораздо более последовательные результаты, не вызывая никаких методов init () между внедренными объектами напрямую, а использую подход тегов метаданных.

TypeError: ошибка № 1009: невозможно получить доступ к свойству или методу ссылки на нулевой объект. в cafeparsley.view :: EmployeeList / _EmployeeList_List1_i () [C: \ dev \ code \ workspace \ Примеры \ CafeParsley \ src \ cafeparsley \ view \ EmployeeList.mxml: 29] в cafeparsley.view :: EmployeeList / _EmployeeList_Array2_c () .core :: DeferredInstanceFromFunction / getInstance () [E: \ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ DeferredInstanceFromFunction.as: 105] в spark.components :: SkinnableContainer / createDeferredContent () [E : \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as: 985] в spark.components :: SkinnableContainer / createContentIfNeeded () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as: 1014] в spark.components :: SkinnableContainer / createChildren () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer. as: 827] в mx.core :: UIComponent / initialize () [E: \ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 7349] в mx.core :: UIComponent / http://www.adobe.com/2006/flex/mx/internal::chil dAdded () [E: \ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 7241] в mx.core :: UIComponent / addChildAt () [E: \ dev \ 4. x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 6947] в spark.components :: Group / addDisplayObjectToDisplayList () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as: 1825] на сайте spark.components :: Group / http: //www.adobe.com/2006/flex/mx/internal :: elementAdded () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as: 1416] в spark.components :: Group / setMXMLContent () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as:512] в spark.components :: Group / set mxmlContent () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ Group.as: 452] в spark.components :: SkinnableContainer / set mxmlContent () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as: 604] в spark.components :: SkinnableContainer / createDeferredContent () [E: \ Dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ компоненты \ SkinnableContainer.as: 986] в spark.components :: SkinnableContainer / createContentIfNeeded () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as: 1014] в искре. компоненты :: SkinnableContainer / createChildren () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ SkinnableContainer.as: 827] в spark.components :: NavigatorContent / createChildren () [E: \ dev \ 4.x \ frameworks \ projects \ spark \ src \ spark \ components \ NavigatorContent.as: 225] в mx.core :: UIComponent / initialize () [E: \ dev \ 4.x \ frameworks \ projects \ framework \ src \ mx \ core \ UIComponent.as: 7349] в cafeparsley.view :: EmployeeList / initialize ()

person Pelted    schedule 13.09.2011