|
TutorialsAndromedA_IOC
A - Generality1 - Definitions1-1 Dependency injectionDependency injection (DI) refers to the practice of injecting dependencies into your code. This design pattern consist of multiple classes or objects which collaborate with each other. You can use different ways to implement this pattern : Hard-coding dependencies : The class instantiates its dependencies (more easy). Example : package
{
public class Writer
{
public function Writer()
{
}
public function write( message:String ):void
{
( new Pen() ).write( message ) ;
}
}
}Looking up dependencies : The class gets the context and looks up its dependencies. The context is an external object who contains all dependencies. Example : package
{
public class Writer
{
public function Writer()
{
}
public function write( message:String ):void
{
var context:Tools = new Tools() ;
context.getPen().write( message ) ;
}
}
}Constructor injection : In this approach the class declares a constructor with parameters for both dependencies ; the dependencies are given on instantiation. Example : package
{
public class Writer
{
public function Writer( pen:Pen )
{
_pen = pen ;
}
private var _pen:Pen ;
public function write( message:String ):void
{
_pen.write( message ) ;
}
}
}Setter Injection : In this approach the class provides setters attributes for both dependencies ; the dependencies are satisfied after instantiation. Example 1 : with an easy setter method package
{
public class Writer
{
public function Writer()
{
}
public var pen:Pen ;
public function setPen( p:Pen ):void
{
pen = p ;
}
public function write( message:String ):void
{
pen.write( message ) ;
}
}
}Example 2 : with a virtual setter property package
{
public class Writer
{
public function Writer()
{
}
private var _pen:Pen ;
public function set pen( p:Pen ):void
{
_pen = p ;
}
public function write( message:String ):void
{
_pen.write( message ) ;
}
}
}Interface Injection : This method use the same method like Setter Injection or Constructor Injection" but the dependencies arguments or properties types are interfaces and not concrete type. Example : package
{
public class Writer
{
public function Writer()
{
}
private var _pen:IPen ;
public function get pen():IPen
{
return _pen ;
}
public function set pen( p:IPen ):void
{
_pen = p ;
}
public function write( message:String ):void
{
(_pen as IPen).write( message ) ;
}
}
}1-2 Inversion of controlInversion of control, or IoC (the other name of the Dependency injection pattern) is a design pattern and set of associated programming techniques in which the flow of control of a system is inverted in comparison to the traditional interaction model. In a sense, inversion of control follows what has been referred to as the "Hollywood Principle"—"don't call us, we will call you". 1-3 Inversion of Control ContainersAn Inversion of Control container is an infrastructural backbone for applications by providing services like lifecycle management, lookup, configuration and dependency resolution.
Dependency resolution : The container should not only configure application objects with simple types, but also manage relationships between them. 2 - eden configuration context file structureThe Andromeda IOC factory pattern is based on the eden format (a subset of the ECMAScript notation), it allows to exchange and interpret data keeping the structure and the type. example 1 : {
configuration : // only in the top-level file
{
// ..
}
,
imports :
[
//..
]
,
objects :
[
//..
]
}example 2 : // only in the top-level file
configuration =
{
// ..
} ;
imports =
[
//..
] ;
objects =
[
//..
];(see the official *eden* google code project page for more informations) The AndromedA IoC structure use the ECMAScript notation and not an XML structure like Spring framework or other light container implementations. Note : You can use a JSON parser to create the 'context object' of the factory. In VEGAS you can use the vegas.string.JSON a custom implementation of the official *JSON* class. The vegas.string.JSON class accept such custom notation as 0xRRGGBB and you can also define JSON expression in your string with or without quotes notation : { "prop" : value } or { 'prop' : value } or { prop : value }. Read the vegas.string.JSON reference for more examples. The main context object contains 3 optional attributes : imports, configuration and objects.
(as a side note, for me JSON is not the good option to use the IOC implementation with AndromedA, The eden format is the best way and the more powerful, and then should be prefered) 3 - The ECMAObjectFactory class3-1 - About and basic example.The ECMAObjectFactory class defines the light container and the IOC factory based ECMASCript in the AndromedA IOC package. This class implement the IFactory interface and contains the important create( [context:Object] ) method who parse an ECMAScript object notation into an object definition. This class extends the asgard.ioc.factory.ObjectFactory super class and the asgard.ioc.core.ObjectDefinition class. It's map all object definition (IObjectDefinition references) to create the objects in your applications. Read first this next example to see the basic usage of the ObjectFactory and ObjectDefinition class : import test.User ;
import andromeda.ioc.core.ObjectDefinition ;
import andromeda.ioc.factory.ObjectFactory ;
import vegas.data.map.HashMap ;
var factory:ObjectFactory = new ObjectFactory();
var properties:HashMap = new HashMap() ;
properties.put("pseudo" , "ekameleon" ) ;
properties.put("url" , "http://www.ekameleon.net/blog" );
var definition:ObjectDefinition = new ObjectDefinition( "test.User" ) ;
definition.setProperties( properties ) ;
definition.setInitMethodName( "initialize" ) ;
factory.addObjectDefinition("user", definition );
var user:User = factory.getObject("user") ;
trace( "# User pseudo : " + user.pseudo ) ; // ekameleon
trace( "# User url : " + user.url ) ; // http://www.ekameleon.net/blogThis factory is inspired from Spring.NET and Spring.JAVA frameworks but use an ECMAScript philosophy (we use a subset of ECMAScript and we stay dynamic). We can create a little example in Flash CS3 with an easy ActionScript 3 source code, we must load the external eden file context/application.eden : objects =
[
{
id : "square" ,
type : "Square" , // The class definition name of the embed symbol in the library of the top-level swf file.
properties :
[
{ name:"x" , value : 100 } ,
{ name:"y" , value : 25 }
]
}
]And in the main layer of the swf file we use this script : import andromeda.ioc.core.ObjectAttribute ;
import andromeda.ioc.core.ObjectDefinition ;
import andromeda.ioc.factory.ECMAObjectFactory ;
import andromeda.ioc.factory.ObjectConfig ;
import andromeda.events.ActionEvent ;
import flash.display.StageAlign ;
import flash.display.StageScaleMode ;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import buRRRn.eden ;
import test.User ;
stage.align = StageAlign.TOP_LEFT ;
stage.scaleMode = StageScaleMode.NO_SCALE ;
var complete:Function = function ( event:Event ):void
{
var loader:URLLoader = event.target as URLLoader ;
var source:String = loader.data ;
var context:Object = eden.deserialize(source) ;
factory.config = new ObjectConfig( context[ ObjectAttribute.CONFIGURATION ] ) ;
factory.create( context[ ObjectAttribute.OBJECTS ] ) ;
}
var debug:Function = function( e:Event ):void
{
trace( e ) ;
}
var main:Function = function( e:ActionEvent ):void
{
trace( e ) ;
var sprite:Sprite = factory.getObject("square") as Sprite ; // use external dll
addChild(sprite) ;
}
var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ;
factory.addEventListener( IOErrorEvent.IO_ERROR , debug ) ;
factory.addEventListener( ProgressEvent.PROGRESS , debug ) ;
factory.addEventListener( Event.COMPLETE , debug ) ;
factory.addEventListener( ActionEvent.START , debug ) ;
factory.addEventListener( ActionEvent.FINISH , main ) ;
var request:URLRequest = new URLRequest( "context/application.eden" ) ;
var loader:URLLoader = new URLLoader() ;
loader.addEventListener( Event.COMPLETE , complete ) ;
loader.load( request ) ;The Square symbol is added to the stage of the SWF and this new instance is defined by the object structure in the external eden file. 3-2 - Inspecting the IOC FactoryThere are some methods and properties of the ECMAObjectFactory which we haven't discussed yet and which you might not need that often. They allow you to inspect the content of an ECMAObjectFactory :
4 - The ECMAObjectLoader class4-1 About and exampleTo load any eden context file and initialize the ECMAObjectFactory singleton you can use an ECMAObjectLoader instance : import andromeda.events.ActionEvent;
import andromeda.ioc.factory.ECMAObjectFactory;
import asgard.net.ECMAObjectLoader ;
var debug:Function = function( e:Event ):void
{
trace( e ) ;
}
var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ;
var loader:ECMAObjectLoader = new ECMAObjectLoader( "application.eden" , "context/" ) ;
loader.addEventListener( ActionEvent.START , debug ) ;
loader.addEventListener( ActionEvent.FINISH , debug ) ;
loader.run() ;The ECMAObjectLoader instance contains by default the reference to the ECMAObjectFactory singleton (You can call it with the ECMAObjectFactory.getInstance() static method). The ECMAObjectLoader use by default an eden loader (asgard.net.EdenLoader) and parser but you can use any other compatible asgard.net.ParserLoader reference like the one implemented in asgard.net.JSONLoader class. This loader is a process (andromeda.process.IAction implementation) and load all the external context files in your applications. This loader encapsulate all process to load the multiple context files who defines the IOC container of the application, create and initialize ECMAObjectFactory wi the full final context object. 4-2 Using multiple context files :We already mentioned that ECMAObjectLoader context can be split into multiple files. In all your context files you can insert the top-level "imports" attribute, an Array of generic object who contains the urls of the other external context files to load. imports :
[
{ ressource : "logging.eden" } ,
{ ressource : "view.eden" } ,
{ ressource : "controller.eden" }
]B - The ECMAScript DOM context of AndromedA IOC.Within the container itself, these object definitions are represented as IObjectDefinition objects, which contain (among other information) the following metadata :
The concepts listed above directly translate to a set of elements the object definition consists of. These elements are listed below :
1 - The basic object context definitionThe basic task of the ECMAObjectFactory context configuration file is declaring the definitions of the objects in the application. Example : consider we would like to configure the following class package test
{
import system.Reflection;
import vegas.core.CoreObject;
/**
* The User class to test the LightContainer.
*/
public class User extends CoreObject
{
/**
* Creates a new User instance.
*/
public function User( pseudo:String = null, name:String =null , address:Address = null )
{
this.pseudo = pseudo ;
this.name = name ;
this.address = address ;
}
/**
* The Address reference of this object.
*/
public var address:Address ;
/**
* The age of the user.
*/
public var age:Number ;
/**
* The fistname of the user.
*/
public var firstName:String ;
/**
* The job of this User.
*/
public var job:Job ;
/**
* The mail of the user.
*/
public var mail:String ;
/**
* The name of the User.
*/
public var name:String ;
/**
* The pseudo of the user.
*/
public var pseudo:String ;
/**
* The url of the User.
*/
public var url:String ;
/**
* Destroy the user.
*/
public function destroy():void
{
trace( this + " destroy.") ;
}
/**
* Initialize the User.
*/
public function initialize():void
{
trace( this + " initialize.") ;
}
/**
* Sets the mail value of this user.
*/
public function setMail( sMail:String ):void
{
mail = sMail ;
}
/**
* Returns the string representation of the object.
* @return the string representation of the object.
*/
public override function toString():String
{
return "[" + Reflection.getClassName(this) + ( pseudo != null ? " " + pseudo : "" ) + "]" ;
}
}
}The corresponding eden configuration : {
id : "user" ,
type : "test.User" ,
arguments :
[
{ value :"eKameleon" } ,
{ value :"ALCARAZ" } ,
{ ref :"address" }
] ,
lazyInit : true , // only if this object is a singleton, the singleton isn't initialized during the factory initialize process.
singleton : true ,
destroy : "destroy" ,
init : "initialize" ,
properties :
[
{ name:"age" , value : 30 } ,
{ name:"firstName" , value : "Marc" } ,
{ name:"job" , ref : "job_dev" } ,
{ name:"url" , value : "http://www.ekameleon.net/blog" }
]
,
methods :
[
{ name:"setMail" , arguments : [ { value :"vegas@ekameleon.net" } ] }
]
}1-1 The 'id' attribute{
id : "user" ,
// ...The id of the object definition in the factory. This id is the key used to obtain a reference to the object (singleton or prototype) import andromeda.ioc.factory.ECMAObjectFactory; import test.User ; //... var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ; var user:User = factory.getObject( "user" ) ; trace(user) ; 1-2 The 'type' attributetype : "test.User" , The fully qualified class name of the object to create with the factory and the current definition. Make sure that this class is included when you compile the application. If the class isn't included in the root application file, you can still use the assemblyName attribute in the current object attribute in another eden context file (see assemblyName). 1-3 The 'properties' attribute properties :
[
{ name:"age" , value : 30 } ,
{ name:"job" , ref : "job_dev" } ,
]There are three ways to define a property value. Using the value attribute { name:"age" , value : 30 } ,This way define a simple pair name-value which can support all native or custom objets valid in the eden parser. You can use String, Boolean, Number, Array, Object, Date, null, undefined... and custom class instance or reference if this class exist in the white list of the eden parser. Using the ref attribute { name:"job" , ref : "job_dev" } ,The ref attribute allows to define dependencies. The value of the ref attribute must point to the id of another object configured in the same ECMAObjectFactory container. 1-4 The 'arguments' attribute arguments :
[
{ value :"eKameleon" } ,
{ value :"ALCARAZ" } ,
{ ref :"address" }
] ,The Array representation of all passed-in argument in the constructor method of the object when the factory create it. This attribute is optional, if the constructor of the class don't contains arguments you can forget this attribute in the eden context of your object definition. The arguments in this Array are defines with an generic object and two ways to define the value of the argument : Using the 'value' attribute { value :"eKameleon" } ,This way define a simple value with all native or custom objets valid in the eden parser. You can use String, Boolean, Number, Array, Object, Date, null, undefined... and custom class instance or reference if this class exist in the white list of the eden parser. Using the 'ref' attribute { ref : "address" }The ref attribute allows to define dependencies. The value of the ref attribute must point to the id of another object configured in the same ECMAObjectFactory container. 1-5 Invoke methods in the 'properties' attribute. properties :
[
{ name:"setMail" , arguments : [ { value :"vegas@ekameleon.net" } ] }
]In the object definitions we can invoke methods when the object is initialize. In the attribute "properties" we can use a property with the attributes 'arguments' !
This methods initialize the object or launch process. This methods are invoked after the properties attribute in the factory. 1-6 - singleton and scope attribute1-6-1 The singleton attribute The object attribute also has a singleton attribute. We omitted it in all previous examples since the default value is true and that is the setting we want in most cases. When the attribute is set to true the IOC Container will cache all instances that were already created and return the cached instances on subsequent requests for the same id. If the attribute is set to false the container will create a new instance each time you request that object. 1-6-2 The scope attribute When you create an object definition what you are actually creating is a recipe for creating actual instances of the class defined by that object definition. The idea that an object definition is a recipe is important, because it means that, just like a class, you can potentially have many object instances created from a single recipe. You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular object definition, but also the scope of the objects created from a particular object definition. The scopes supported for the moment in the ECMAScript IOC factory of AndromedA are listed below :
By default all object definition are "prototype" but you can change this state with the attributes "scope" or "singleton" in the ECMAScript object definition. You can find in the package andromeda.ioc.core the static enumeration class ObjectScope to validate the scope of your object definitions. If you use the "scope" attribute in your ECMAScript IOC object definition this attribute reset the "singleton" attribute. The non-singleton, "prototype" scope of definition deployment results in the creation of a new object instance every time a request for that specific object is made. 1-6-3 Lazy initialization lazyInit : true , // only if this object is a singleton, the singleton isn't initialized during the factory initialize process. Finally there is a lazyInit attribute that only affects singleton object definition. The default value is false. If the lazyInit attribute is true the object will be created the first time it is requested otherwise the object is created during the initialization of the object definition in the factory. This may be useful for application initialization or if you want to detect possible runtime errors early. 1-7 FactoriesIn the object definitions, in the IoC_ factory, you can use "factory attributes" to defines a custom strategy used when the object is created. This feature replace the natural strategy defines in the IoC_ factory to creates the objects with a specific type (use the new keyword). This attributes are based on stategy objects in your factory who implement the IObjectStrategyFactory interface. The factory attributes are :
1-7-1 Static Factory Methods See first a little example and we create an instance of the User class a static factory method. package test
{
public class User
{
public function User( name:String )
{
this.name = name ;
}
public var name:String ;
}
}We need to use the following static factory method : package test
{
public class UserFactory
{
public static function create( name:String):User
{
return new User(name) ;
}
}
}In the eden IOC context file you can use now this static factory method with the attribute staticFactoryMethod : {
id : "my_user" ,
type : "test.User" ,
staticFactoryMethod : { type : "test.UserFactory" , name:"create" , arguments: [ { value : "ekameleon" } ] }
}1-7-2 Factory Methods For this example we want to create a User instances with a new strategy with the factory method. package test
{
public class User
{
public function User( name:String )
{
this.name = name ;
}
public var name:String ;
}
}We need to use the following generic factory class : package test
{
import vegas.errors.IllegalArgumentError ;
public class UserFactory
{
public function UserFactory ( blackList:Array )
{
this.blackList = [] ;
}
public var blackList:Array ;
public function create( name:String):User
{
if ( blackList.indexOf( name ) > -1 )
{
throw new IllegalArgumentError(this + " create failed : the user can't be created, is register in the black list of the factory : " + name ) ;
}
}
}
}In the eden IOC context file you can use now this static method with the attribute factoryMethod : {
id : "user_factory" ,
type : "test.UserFactory" ,
arguments :
[
{ value : "lunas" } ,
{ value : "pegas" }
]
}
,
{
id : "my_user" ,
type : "test.User" ,
factoryMethod : { factory:"user_factory" , name:"create" , arguments: [ { value : "ekameleon" } ] }
}The factoryMethod attribute value is a generic object with the properties :
1-8-3 Static Factory Properties For this example we want to create a new class Civilty who contains a static enumeration list of String values. package test
{
/**
* The civility static enumeration list.
*/
public class Civility
{
/**
* Determinates the "man" civility.
*/
public static const MAN:String = "man" ;
/**
* Determinates the "woman" civility.
*/
public static const WOMAN:String = "woman" ;
}
}In your IOC you can create an object definition who use a strategy based on get the value or the reference of the object in a static constant or attribute in a class. This strategy use the staticFactoryProperty attribute in the object definition : objects :
{
{
id : "man" ,
type : "String" ,
staticFactoryProperty : { type:"test.Civility" , name:"MAN" }
}
}In the ActionScript source code you can gets the constant value with the easy next script : var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ;
var civility:String = factory.getObject("man") ;
trace( civility ) ; // man
This example is really basic but for me this strategy is very important. For example in a MXML Flex application to retrieve the Application reference in your IoC definitions you can write : objects :
{
{
id : "myPanel" ,
type : "mx.controls.Panel"
}
{
id : "application" ,
type : "mx.core.Application" ,
singleton : true ,
staticFactoryProperty : { type:"mx.core.Application" , name:"application" } ,
methods :
[
{ name:"addChild" , arguments:[ { ref:"myPanel" } ] }
]
}
}The object definition with the id "application" is a singleton, this singleton is auto created when the IoC container is initialized. The object is not a new mx.core.Application" instance but the main Application reference of your MXML application. The Panel with the id "myPanel" in the IoC factory is auto inserted in the application with the addChild method. 1-8-4 Static Factory Properties TODO 1-9 - The identify attributeThis attribute work only with a singleton object definition and if the type of the object definition implements the vegas.core.Identifiable interface. The vegas.core.Identifiable defines object with a unique identifier id. This objects exist in lot's of tools and implementations in the libraries of VEGAS. When the identify attribute is true, the new Identifiable object is filled with the id value of this IObjectDefinition. Example in a new external file with a eden objects inside : objects =
[
{
id : "vo_01" ,
type : "andromeda.vo.NetServerInfoVO" ,
singleton : true ,
identify : true ,
arguments :
[
{
application : "local" ,
level : "error" ,
code : "application_error" ,
description : "An error is invoqued in the application" ,
line : 3 ,
methodName : "noMethod" ,
serviceName : "noService"
}
]
}
] ;The andromeda.vo.NetServerInfoVO class implements the vegas.core.Identifiable interface. Now we load this external context file : import andromeda.ioc.factory.ECMAObjectFactory ;
import andromeda.ioc.factory.ObjectConfig ;
import andromeda.events.ActionEvent ;
import andromeda.vo.NetServerInfoVO ;
import flash.display.StageAlign ;
import flash.display.StageScaleMode ;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import system.eden ;
////// enforced the linked class in the swf.
var linkedClass:Array =
[
NetServerInfoVO
]
//////
stage.align = StageAlign.TOP_LEFT ;
stage.scaleMode = StageScaleMode.NO_SCALE ;
var complete:Function = function ( event:Event ):void
{
var loader:URLLoader = event.target as URLLoader ;
var source:String = loader.data ;
var app:Object = eden.deserialize(source) ;
factory.create( app.objects ) ;
}
var debug:Function = function( e:Event ):void
{
trace( "# " + e.type ) ; // # onStarted
}
var main:Function = function( e:ActionEvent ):void
{
trace( "# " + e.type ) ; // # onFinished
var id:String = "vo_01" ;
// NetServerInfoVO implements the vegas.core.Identifiable interface
var info:NetServerInfoVO = factory.getObject( id ) ;
// The id of the vo is auto populated if the identify property
// of the ObjectDefinition of this object is true.
trace( "info id : " + info.id ) ; // info id : vo_01
}
var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ;
// if true all singleton Identifiable object are populated with the id of the definition
// factory.config.identify = true ;
factory.addEventListener( IOErrorEvent.IO_ERROR , debug ) ;
factory.addEventListener( ProgressEvent.PROGRESS , debug ) ;
factory.addEventListener( Event.COMPLETE , debug ) ;
factory.addEventListener( ActionEvent.START , debug ) ;
factory.addEventListener( ActionEvent.FINISH , main ) ;
var request:URLRequest = new URLRequest( "context/application_identify.eden" ) ;
var loader:URLLoader = new URLLoader() ;
loader.addEventListener( Event.COMPLETE , complete ) ;
loader.load( request ) ;
The id property value of the NetServerInfoVO instance is "vo_01", the same identifier in the object definition of this instance in the factory. This attribute interact with the ObjectConfig reference of the ObjectFactory container (see the paragraph 3 - The top-level configuration attribute in the next part of this tutorial). 2 - Object lifecycle methodsIn some cases you may have classes with methods that need to be invoked when the object is initialized or when the object is destroyed. {
id : "user" ,
type : "test.User" ,
destroy : "destroy" ,
init : "initialize"
}The init attribute defines the initialization callback method used by factory when the object is created. For the moment the destroy method is used only when the object definition is a "singleton" and when it is removed from the IOC container with the method removeSingleton( id ) . ECMAObjectFactory.removeSingleton("user") ; // the destroy method of the instance is invoked In the future the destroy method should be invoked when the container is fully disposed. 3 - The top-level configuration attributeIf this attribut is not null, it fill the ObjectFactory.config property ( andromeda.ioc.factory.ObjectConfig instance ). In this object you can find attributes listed below :
configuration :
{
defaultInitMethod : "init" ,
defaultDestroyMethod : "destroy" ,
identify : true ,
typePolicy : "all" ,
typeAliases :
[
{ alias:"Sprite" , type:"flash.display.Sprite" } ,
{ alias:"TextField" , type:"flash.text.TextField" }
]
}
The corresponding ActionScript configuration instruction in ActionScript is : import andromeda.ioc.core.TypePolicy ;
import andromeda.ioc.factory.ECMAObjectFactory ;
import andromeda.ioc.factory.ObjectConfig ;
var factory:ECMAObjectFactory = ECMAObjectFactory.getInstance() ;
var config:ObjectConfig = new ObjectConfig() ;
config.defaultInitMethod = "init" ;
config.defaultDestroyMethod = "destroy" ;
config.identify = true ;
config.typePolicy = TypePolicy.ALL ;
config.typeAliases =
[
{ alias:"Sprite" , type:"flash.display.Sprite" } ,
{ alias:"TextField" , type:"flash.text.TextField" }
]
factory.config = config ;
3-1 The defaultInitMethod and defautDestroyMethod attributeThe defaultInitMethod attribute defines the IOC container which will recognize a method called with the value name of this attribute, and when an object is being created and assembled, if the object's class has such a method, it will be invoked at the appropriate time. Destroy method callbacks are configured similarly using the defaultDestroyMethod attribute on the top-level configuration attribute. The use of this feature specifying an initialization and destroy method callback on each and every object is great for enforcing consistent naming convention for methods callbacks. You can always override the default initialization and destroy method callback by specifing the method name using the init and destroy attributes of the object definition in the IOC ECMASCript DOM. If you use multiple context files to defines you ECMAScript IOC factory the top-level property is used. You must use one only defaultInitMethod and defaultDestroyMethod attributes in your context files. 3-2 The identify attributeThis attribute is a boolean and indicates if the ObjectFactory container check the object definition when a new object is created. If the new object is a singleton in the factory and if the type of this object implements the vegas.core.Identifiable interface, the id property of the Identifiable object is populate with the id value of the current IObjectDefinition. Example in the IOC context : {
configuration :
{
identify : true
}
,
{
objects :
[
{
id : "my_sprite" ,
type : "asgard.display.CoreSprite" ,
singleton : true , // must be a singleton
}
]
}
}In this example the asgard.display.CoreSprite class is Identifiable. When the IOC context is loading you can test this code :
import andromeda.ioc.factory.ECMAObjectFactory ;
import asgard.display.CoreSprite ;
var mySprite:CoreSprite = ECMAObjectFactory.getInstance.getObject("my_sprite") as CoreSprite ;
trace( mySprite.id ) ; // my_sprite
The object is auto identify with the id attribute. This feature is very important to auto populate all Identifiable objects in the application. Note : If the object definition identify attribute is strictly false the identify attribute in the config object is not used. 3-3 The typePolicy and typeAliases attributesThe typePolicy attribute definine the policy used by the IOC container over the type value of the object definition when the object is build in the factory. Example : {
configuration :
{
typePolicy : "alias" ,
typeAliases :
[
{ alias:"Sprite" , type:"flash.display.Sprite" } ,
{ alias:"TextField" , type:"flash.text.TextField" }
]
}
,
{
objects :
[
{ id:"my_sprite" , type:"Sprite" } ,
{ id:"my_field" , type:"TextField" }
]
}
}// TODO finish this point !! |
Sign in to add a comment
