Flicc

Dependency Injection For Flex

Mxml based dependency injection for Flex

Rather than emulating existing dependency injection frameworks, Flicc has been built from the ground up to work with Flex. Flicc works with the existing Flex event model to allow you to easily inject objects on to Mxml components without having to pass factory references around your application or introduce global state, as well as working well with modular applications. Flicc also makes use of the dynamic features of Actionscript 3.0 to keep factory configuration as small as possible with minimal boiler-plate.

If you have any questions regarding Flicc or have any feedback or suggestions then please get in touch at mike dot herron at talk21 dot com.

Tutorial

The tutorial here is also available as part of the Full Download. The samples referenced throughout are available as part of the full download as both source code and executable SWFs with View Source ability.

1. The Basics

1.1. Creating a Factory

Like most Dependency Injection frameworks, Flicc is based around two main components: a configuration that defines one or more objects along with their dependencies, and a factory that creates objects (or configures existing objects) based on this configuration. In Flicc, the MxmlObjectFactoryConfig class is used to define configuration and the MxmlObjectFactory is used to create or configure objects.

As their names suggest, the MxmlObjectFactoryConfig and MxmlObjectFactory classes are designed to be used as tags in an MXML document. The below example shows how a factory configuration, Config, is created by extending the MxmlObjectFactoryConfig and populating the descriptors element.

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
   <descriptors>

      <Object objectId="welcomeModel" clazz="{ SimpleWelcomeModel }">
         <message>Hello World</message>
      </Object>

   </descriptors>
</MxmlFactoryConfig>

The configuration is then passed to an instance of MxmlObjectFactory on the main application:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:flicc="flicc.factory.mxml.*"
    xmlns:sample1="sample1.*"
    creationComplete="init()">

    <flicc:MxmlObjectFactory id="factory">
      <sample1:Config />
    </flicc:MxmlObjectFactory>

    <sample1:WelcomeComponent factory="{ factory }"/>

</mx:Application>

The configuration in this example describes a single object of type SimpleWelcomeModel with the unique identifier of welcomeModel. The child element, <message> is set to Hello World - this is how dependencies are expressed in Flicc. When the factory creates this object, it will set the message property on SimpleWelcomeModel to Hello World.

Now that the factory has been configured, it's possible to create objects using the getInstance method. The custom component, WelcomeComponent, uses the factory to create an instance of SimpleWelcomeModel:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net"
   creationComplete="init()">

   <mx:Script>
      <![CDATA[

         import flicc.factory.IObjectFactory;

         public var factory : IObjectFactory;

         [Bindable]
         public var welcomeModel : IWelcomeModel;

         public function init() : void
         {
            welcomeModel = factory.getInstance( "welcomeModel" );
         }

      ]]>
   </mx:Script>

   <mx:Label text="{ welcomeModel.message }" />

</mx:VBox>

1.2. Configuring Mxml Components

Rather than passing factory instances around your application, you can use the Configure tag along with the FliccListener to inject objects on to MXML components. Firstly, wrap a FliccListener around the factory:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net"
   xmlns:sample="configuringcomponents.*">

   <flicc:FliccListener>
      <flicc:MxmlObjectFactory>
         <sample:Config />
      </flicc:MxmlObjectFactory>
   </flicc:FliccListener>

   <sample:WelcomeComponent id="helloWorld" />

</mx:Application>

Then, add the Configure tag to the component you want to configure using the factory:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net">

   <flicc:Configure />

   <mx:Script>
      <![CDATA[
         [Bindable]
         public var welcomeModel : IWelcomeModel;
      ]]>
   </mx:Script>

   <mx:Label text="{ welcomeModel.message }" />

</mx:VBox>

Finally, add a Component tag to the factory configuration with an objectId matching the Flex id of the component that defines what objects you want to inject:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
   <descriptors>

      <Component objectId="helloWorld">
         <welcomeModel>
            <Object clazz="{ SimpleWelcomeModel }">
               <message>Hello World</message>
            </Object>
         </welcomeModel>
      </Component>

   </descriptors>
</MxmlFactoryConfig>

So how does this work? When the WelcomeComponent's creationComplete event fires, the Configure tag dispatches a FliccEvent.CONFIGURE event that bubbles up the display object hierarchy. The FliccEvent contains 2 properties - objectId and target. By default, the Configure tag sets the target to the component that it was declared on, and the objectId to the flex id of the component. The FliccListener will capture this event and make a call to MxmlObjectFactory.configure using the objectId and target from the FliccEvent as arguments. The configure method will then look for a descriptor matching the provided objectId, and apply the described dependencies to target. In this case, there is a Component element has been declared with an objectId that matches the id of the WelcomeComponent - so the welcomeModel property will be set to an instance of SimpleWelcomeModel. (Note that Component is just an Object element that has no clazz defined - it can be used instead of Object to more clearly signal intent)

This method is far more flexible than the previous method. Firstly, there's no need pass instances of MxmlObjectFactory to every component in the application. Secondly, objectId's don't need to be hardcoded within components, making them far easier to reuse. For example, using the Configure tag, another instance of the WelcomeComponent can be declared and configured to display a different message:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net"
   xmlns:sample="configuringcomponentss.*">

   <flicc:FliccListener>
      <flicc:MxmlObjectFactory>
         <gettingstarted:Config />
      </flicc:MxmlObjectFactory>
   </flicc:FliccListener>

   <sample:WelcomeComponent id="helloWorld" />
   <sample:WelcomeComponent id="goodbyeWorld" />

</mx:Application>

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
   <descriptors>

      <Component objectId="helloWorld">
         <welcomeModel>
            <Object clazz="{ SimpleWelcomeModel }">
               <message>Hello World</message>
            </Object>
         </welcomeModel>
      </Component>

      <Component objectId="goodbyeWorld">
         <welcomeModel>
            <Object clazz="{ SimpleWelcomeModel }">
               <message>Good Bye World</message>
            </Object>
         </welcomeModel>
      </Component>

   </descriptors>
</MxmlFactoryConfig>

The code for the WelcomeComponent doesn't change - all that's required is a new Component definition in the factory configuration. Using the Configure tag also means that you don't have Flicc references littered throughout your code base, just a single MMXML tag where required - Actionscript classes in your application aren't aware of Flicc at all, making unit testing and reuse a lot easier.

1.3. Configure Tag Options

The Configure tag can be customised in several ways.

The target property can be set to configure a component other than the one the tag was declared on. This is useful when you want to configure a component whose source code you don't have direct access to, or a component you want to be able to package and reuse across projects and therefore not have direct references to Flicc. The below example shows how a DateField component can be configured by specifying the target property on the Configure tag.

<flicc:Configure target="{ selectDate }" />
<mx:DateField id="selectDate" />

The id property of the target must still map to a Component configuration element:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
    <descriptors>
		
        <Component objectId="selectDate">
            <formatString>DD-MM-YYYY</formatString>
            <selectedDate>{ new Date() }</selectedDate>
        </Component>
		
    </descriptors>
</MxmlFactoryConfig>

The objectId property can be set to configure a component with a hardcoded ID rather than relying on the declared Flex id of the component. Sometimes this is nessecary when more than one component in the same scope must be configured using the same Component definition:

<flicc:Configure target="{label1}"
    objectId="label" />
    
<flicc:Configure target="{label2}"
    objectId="label" />
        
<mx:Label id="label1" />
<mx:Label id="label2" />

Finally, the trigger property can be set to define what event the Configure tag listens for before dispatching the FliccEvent. By default the Configure tag uses creationComplete, but you might want to wait until the show event before configuring a component for performance reasons:

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" 
   xmlns:flicc="http://flicc.sourceforge.net"
   visible="false">
   
   <flicc:Configure target="{hiddenLabel}" trigger="show" />
    
   <mx:Label id="hiddenLabel" />
   
</mx:VBox>

Remember that the Configure will always listen for the trigger event on the component it is declared on, not the target.

2. Defining Configuration

2.1. Referencing Objects

You can include references to other objects within the configuration by using the Ref element. The to property must match the objectId of another object within the same configuration:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
   <descriptors>

      <Component objectId="goodbyeWorld">
         <welcomeModel><Ref to="GoodbyeModel" /></welcomeModel>
      </Component>

      <Object objectId="GoodbyeModel" clazz="{ SimpleWelcomeModel } ">
         <message>Good Bye World</message>
      </Object>

   </descriptors>
</MxmlFactoryConfig>

2.2. Single Instances

By default, each object created by the factory will be cached and reused based on the objectId. To create a new instance whenever the object is required, set the isSingleton property on Object to false:

<Object objectId="GoodbyeModel" clazz="{ SimpleWelcomeModel } " isSingleton="false">
    <message>Good Bye World</message>
</Object>

To have the factory create all singleton objects at application start up, set the preInstantiateSingletons property to true:

<flicc:MxmlObjectFactory id="factory">
    <sample1:Config preInstantiateSingletons="true"/>
</flicc:MxmlObjectFactory>

2.3. Injecting Lists

The List element can be used to describe IList implementations or Arrays. The elements will be added to the list in the order they appear in the configuration. List provides an instance of the ArrayCollection class if the clazz property is not specified:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml">
   <descriptors>

      <Component objectId="randomWelcome">
         <welcomeModel>
            <Object clazz="{ RandomWelcomeMessage }">
               <messages><Ref to="messages" /></messages>
            </Object>
         </welcomeModel>
      </Component>

      <List objectId="messages">
         <mx:String>Hey World</mx:String>
         <mx:String>How are things World?</mx:String>
         <mx:String>Hello World</mx:String>
         <mx:String>Nice to see you, World</mx:String>
         <mx:String>Go away World!</mx:String>
      </List>

   </descriptors>
</MxmlFactoryConfig>

List config elements can contain other Objects, Ref elements, and "primitive" types like String and Number. If the List contains primitive types only, the SimpleList element can be used to write this as a comma seperated string:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml">
   <descriptors>

   <Component objectId="randomWelcome">
      <welcomeModel>
         <Object clazz="{ RandomWelcomeMessage }">
            <messages><Ref to="messages" /></messages>
         </Object>
      </welcomeModel>
   </Component>

   <SimpleList objectId="messages">
      Hey World, How are things World?, Hello World,Nice to see you, World,Go away World!
   </SimpleList>

   </descriptors>
</MxmlFactoryConfig>

Note that any whitespace before and after each value will be trimmed.

2.4. Constructor Arguments

Constructor arguments can be passed using the constructor property on Object. The arguments are passed in the order they are defined in the configuration:

<Object clazz="{ RandomWelcomeMessage }" objectId="randomMessage">
   <constructor>
      <Ref to="messages" />
   </constructor>
</Object>

<SimpleList objectId="messages">
   Hey World, How are things World?, Hello World,Nice to see you, World,Go away World!
</SimpleList>

You can pass up to 10 arguments to a constructor in Flicc.

2.5. Initialise and Destroy

You can specify a method for Flicc to invoke once it has fully instantiated an object and satisfied it's dependencies using the initialiseMethod property:

<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net">
   <descriptors>
      
      <Component objectId="helloWorld">
         <welcomeModel>
            <Object clazz="{ SimpleWelcomeModel }" initialiseMethod="init" />
         </welcomeModel>
      </Component>
      
   </descriptors>
</MxmlFactoryConfig>

package initanddestroy
{
   
public class SimpleWelcomeModel
{
   private var _message : String;
   
   public function get message() : String
   {
      return _message; 
   }
   
   public function init() : void
   {
      _message = "Init method called on SimpleWelcomeModel";
   }
		
}

The initialiseMethod must take no arguments. You can also specify a destroyMethod which Flicc should call when the factory that created the object is destroyed - see the section on Modules for more details.

2.6. Object Place Holders

Since Mxml is already very adept at declaratively instantiating objects, you can use the ObjectPlaceHolder tag to write an Mxml component declaration within the factory when there are no other references you wish to inject on to the object. This is useful for injecting RPC classes for example:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:rpc="mx.rpc.http.*">
   <descriptors>

   <Component objectId="welcome">
      <welcomeModel><Ref to="httpMessage" /></welcomeModel>
   </Component>

   <Object clazz="{ HttpWelcomeModel }" objectId="httpMessage">
      <constructor>
         <Ref to="messageService" />
      </constructor>
   </Object>

   <ObjectPlaceHolder objectId="messageService">
      <rpc:HTTPService url="message.xml"
         resultFormat="e4x"/>
   </ObjectPlaceHolder>

   </descriptors>
</MxmlFactoryConfig>

Creating objects directly using ObjectPlaceHolder provides a greater degree of compile-time type checking.

2.7. Event Handlers

The handlers element can be used to listen to an event from another factory Object or a property on the target class. In the below sample, the IWelcomeModel implementation listens for the NAME_CHANGED event on the INameModel implementation:

<?xml version="1.0" encoding="utf-8"?>
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net">

   <flicc:Configure />

   <mx:Script>
      <![CDATA[
         import eventlisteners.INameModel;
         import eventlisteners.IWelcomeModel;

         [Bindable]
         public var nameModel : INameModel;

         [Bindable]
         public var welcomeModel : IWelcomeModel;
      ]]>
   </mx:Script>

   <mx:FormItem label="Name">
      <mx:TextInput id="nameInput" text="{ nameModel.name }"
         change="nameModel.name = nameInput.text" />
   </mx:FormItem>

   <mx:FormItem>
      <mx:Label text="{ welcomeModel.message }" />
   </mx:FormItem>

</mx:Form>

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml">

   <descriptors>

   <Component objectId="nameForm">
         <nameModel>
            <Ref to="nameModel" />
         </nameModel>
         <welcomeModel>
            <Ref to="welcomeModel" />
         </welcomeModel>
   </Component>

   <Object objectId="nameModel" clazz="{ EventDispatchingNameModel }" />

   <Object objectId="welcomeModel" clazz="{ SimpleWelcomeModel }">
      <handlers>
         <EventHandler>
            <eventName>{ NameModelEvent.NAME_CHANGED }</eventName>
            <handler>handleNameChanged</handler>
            <source><Ref to="nameModel" /></source>
         </EventHandler>
      </handlers>
   </Object>

   </descriptors>

</MxmlFactoryConfig>

package sample8
{

import flash.events.EventDispatcher;

public class EventDispatchingNameModel extends EventDispatcher implements INameModel
{
   private var _name : String;

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

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

      dispatchEvent( new NameModelEvent( value ) );
   }
}

}

package sample8
{

public class SimpleWelcomeModel implements IWelcomeModel
{
   private var _message : String;

   public function set message( value : String ) : void
   {
      _message = value;
   }

   [Bindable]
   public function get message() : String
   {
      return _message;
   }

   public function handleNameChanged( event : NameModelEvent ) : void
   {
      message = "Hello " + event.name;
   }

}

}

To listen to an event from a member variable rather than another object, set the source property to the name of the member rather than using the Ref element. So in the above example, if the WelcomeModel contained an instance of the EventDispatchingNameModel on a member variabled called name, then source would be set to name.

2.8. Splitting Up Configuration

The factory configuration can be divided in to several smaller configuration classes using the externalDescriptors property on MxmlFactoryConfiguration. The top level configuration class must still extend MxmlFactoryConfig with the child configuration elements extending MxmlDescriptors:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:splittingupconfig="splittingupconfig.*">

   <externalDescriptors>
      <splittingupconfig:ListConfig />
   </externalDescriptors>

   <descriptors>

      <Component objectId="randomWelcome">
         <welcomeModel>
            <Object clazz="{ RandomWelcomeMessage }">
               <messages><Ref to="messages" /></messages>
            </Object>
         </welcomeModel>
      </Component>

   </descriptors>

</MxmlFactoryConfig>

<?xml version="1.0" encoding="utf-8"?>
<MxmlObjectDescriptors xmlns="http://flicc.sourceforge.net"
    xmlns:mx="http://www.adobe.com/2006/mxml">
    <descriptors>

   <SimpleList objectId="messages">
      Hey World, How are things World?, Hello World,Nice to see you, World,Go away World!
   </SimpleList>

    </descriptors>
</MxmlObjectDescriptors>

Child MxmlObjectDescriptors may contain other MxmlDescriptors referenced through the externalDescriptors element and so on.

3. Using Flicc with Modules

3.1. Configuring Modules

You can include Configure tags on components loaded as part of a Module and Flicc will treat them just as it would any other component in the display hierarchy. Taking advantage of this, you can load Modules and use the parent Applictions MxmlObjectFactory to configure the Modules components. Alternativley, rather than having to include every required component definition in the parent Applications factory configruation, each Module can define it's own factory and configuration - again the Configure tag will use the first MxmlObjectFactory it finds.

The below sample application loads two Modules - one with its own factory and one wihtout:

<FliccListener>
   <MxmlObjectFactory>
      <sample:BasicModuleConfig />
   </MxmlObjectFactory>
</FliccListener>
      
<mx:HDividedBox width="100%" height="100%">
   <mx:ModuleLoader url="ModuleWithFactory.swf" 
      id="moduleWithFactory" 
      width="50%"/>
   <mx:ModuleLoader url="ModuleWithoutFactory.swf" 
      id="moduleWithoutFactory"
      width="50%" />      
</mx:HDividedBox>

The Module without a factory includes a Configure tag with the objectId of moduleComponent. This maps to a Component definition in the parent Application factory config:

<mx:Module>
               
   <mx:Script>
   <![CDATA[
      import basicmoduleapplication.WelcomeModel;
      
      [Bindable]
      public var model : WelcomeModel;
   ]]>
   </mx:Script>
   
   <Configure objectId="modulecomponent" />
   
   <mx:Label fontWeight="bold" text="Module Without Factory" />
   <mx:Label text="{model.message}" />

</mx:Module>

<Component objectId="modulecomponent">
    <model>
        <Object clazz="{WelcomeModel}">
           <message>This is from the parent application!</message>
        </Object>
    </model>
</Component>

When the creationComplete event of the Module fires, the MxmlObjectFactory in the parent Application will be used to the configure the module.

Rather than using the parent MxmlObjectFactory, the other Module declares it's own factory and configuration. The Configure tag is used in the same way, but now the first FliccListener in the display hierarchy is the one on the Module rather than the parent Application - so this will be used to to configure components.

<mx:Module>
    
   <mx:Script>
      <![CDATA[
         import basicmoduleapplication.WelcomeModel;
         
         [Bindable]
         public var model : WelcomeModel;
      ]]>
   </mx:Script>
   
   <FliccListener>
      <MxmlObjectFactory>
         <sample:ModuleConfig />
      </MxmlObjectFactory>
   </FliccListener>
   
   <Configure objectId="component" />
      
   <mx:Label fontWeight="bold" text="Module With Factory" />
   <mx:Label text="{model.message}" />
   
</mx:Module>

<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml">
   <descriptors>
   
   <Component objectId="component">
       <model>
           <Object clazz="{WelcomeModel}">
               <message>This is from the Module config!</message>
           </Object>
       </model>
   </Component>

   
   </descriptors>
</MxmlFactoryConfig>

3.2. Sharing Objects

You can also use the ExternalObjects tag to pass objects from a parent Application in to the Modules factory, and then have these objects injected on to components in the Module. In the below example, the Customers object is first provided to the loaded module using the child property of ModuleLoader:

<mx:Script>
<![CDATA[

   [Bindable]
   public var model : Customers;
       
   private function handleModuleReady() : void
   {
      var module : ICustomerModule = 
            ICustomerModule( viewCustomer.child );
      
      module.customers = model;
   }
     
]]>
</mx:Script>
   
<mx:ModuleLoader 
   id="viewCustomer" 
   label="View Customer" 
   url="viewcustomermodule.swf"
   ready="handleModuleReady()"
   width="100%"
   height="100%" />

The Module's factory then declares an ExternalObjects instance on it's factory configuration, binding the Customers instance to a dynamic property named customers:

<mx:Script>
   <![CDATA[
      
      import sharingmodule.Customers;
      
      [Bindable]
      private var _customers : Customers;
      
      public function set customers( value : Customers ) : void
      {
         this._customers = value;
      }
      
   ]]>
</mx:Script>

<FliccListener>
   <MxmlObjectFactory id="factory">
      <sample:ViewCustomerModuleConfig>
         <ExternalObjects customers="{ _customers }" />
      </sample:ViewCustomerModuleConfig>
   </MxmlObjectFactory>
</FliccListener>

<sample:ViewCustomerComponent id="viewCustomerComponent" />

The Customers instance can now be referred to within the factoy configuration using the objectId of customers:

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:mx="http://www.adobe.com/2006/mxml">
   <descriptors>
        
   <Component objectId="viewCustomerComponent">
      <model>
         <Ref to="customers" />  
      </model>
   </Component>

   </descriptors>
</MxmlFactoryConfig>

3.3. Destroying Factories

Before you unload a Module that uses Flicc, you can call destroy on the MxmlObjectFactory of the Module - this will cause the factory to release all references to any objects it has created and invoke the destroyMethod on any created object that has specified one.

The example below uses the ModuleLoader to load and unload a Module. The Module implements the IFliccModule interface which contains one method, unloadFactory. When the Module is unloaded by the parent application, this method is invoked:

<mx:Script>
        
      private var module : IModuleInfo;
      private var moduleInstance : IFliccModule;
        
      private function loadModules() : void
       {
         module = ModuleManager.getModule("DestroyableModule.swf");
         module.load();
      }
        
      private function unloadModule() : void
      {
         if(moduleInstance)
            moduleInstance.unloadFactory();               

         moduleContainer.removeAllChildren();
   
         moduleInstance = null;      
      }
           
      private function loadModule() : void
      {
         if(moduleInstance)
              unloadModule();
                              
         var newModuleInstance : DisplayObject 
            = DisplayObject( module.factory.create() );
                    
         moduleContainer.addChild( newModuleInstance );

         moduleInstance = IFliccModule( newModuleInstance );
      }

</mx:Script>
  
<mx:HBox width="100%">
    <mx:Button label="Load Module" click="loadModule()" />
    <mx:Button label="Unload Module" click="unloadModule()" />
</mx:HBox>

<mx:Canvas id="moduleContainer" width="100%" height="100%" />

The actual Module component invokes the destroy method on its factory when unloadFactory is invoked:

<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flicc="http://flicc.sourceforge.net" 
   xmlns:sample="destroyablemodule.*"
   styleName="module"
   width="100%"
   height="100%"
   implements="unloadingmoduleapplication.IFliccModule">

   <flicc:FliccListener>
      <flicc:MxmlObjectFactory id="factory">
         <sample:ModuleConfig />
      </flicc:MxmlObjectFactory>
   </flicc:FliccListener>
   
   <flicc:Configure id="module" /> 
 
   <mx:Script>
         import unloadingmoduleapplication.WelcomeModel;
     
         [Bindable]
         public var model : WelcomeModel;
         
         public function unloadFactory() : void
         {
             factory.destroy();
         }
   </mx:Script>
 
   <mx:Label text="Message: {model.message}" />
   
</mx:Module>

This causes the factory to call the destroyMethod (if defined) on any objects it has created. In this case, the WelcomeModel created by the factory defined a destroy method named 'cleanUp':

<?xml version="1.0" encoding="utf-8"?>
<MxmlFactoryConfig xmlns="http://flicc.sourceforge.net"
   xmlns:sample="modularapplication.*"
   xmlns:mx="http://www.adobe.com/2006/mxml">
   <descriptors>
        
   <Component id="module">
       <model>
           <Object clazz="{ WelcomeModel }"  initialiseMethod="init" 
              destroyMethod="cleanUp"/>
       </model>
   </Component>

   </descriptors>
</MxmlFactoryConfig>

The WelcomeModels cleanUp method simply displays an Alert, but the destroyMethod can be used to remove references from Singletons and peform any other required clean up when unloading modules.