Crux Dependency Injection
Crux Dependency Injection
Page Contents:
- Dependency Injection Overview
- Inject by type
- Inject by name
- Inject bean property
- Two way bindings
- Setter injection
- Injection destination
Dependency Injection Overview
The IoC Container of Crux is the BeanProvider
class. Any beans defined in a registered BeanProvider
can be injected into other registered beans or into views added to the display list.
Defining an injection target is done using the [Inject]
metadata tag. Common injection scenarios include the following:
- Inject Model into View
- Inject Model into Controller
- Inject Delegate into Controller
- Inject Service into Delegate
Due to restrictions imposed by runtimes, Crux cannot inject into private
, protected
or internal
members.
By default, injections in view components happen during the ADDED_TO_STAGE
event. It is important to understand that this means that injections occur after the initComplete
event. If you need to trigger logic during creation that depends on injections, use a [PostConstruct]
method.
Note:
ADDED_TO_STAGE
is a SWF event. In Javascript you need to add a bead to your Application beads calledJSStageEvents
to simulated stage events likeADDED_TO_STAGE
or ‘REMOVED_FROM_STAGE`
Inject by type
If you define exactly one bean of a given type you can inject it into a matching destination with a plain [Inject]
tag. Note this also supports injecting a concrete implementation of an interface to which the destination is typed. In other words, if a property decorated with [Inject]
is of type IUserService
, Crux will correctly inject a bean implementing that interface, such as UserService
or MockUserService
.
[Inject]
public var model:IUserModel;
Best Practice. You should inject by type whenever possible. It avoids reliance on string based names, which can lead to run time errors caused by misspellings.
Automatic Creation and Injection of Built-In Helper Classes. If Crux encounters an
[Inject]
tag for a property typed toServiceHelper
,IServiceHelper
,URLRequestHelper
,IURLRequestHelper
, orMockDelegateHelper
, and there is no matchingBean
defined in aBeanProvider
, Crux will automatically create a bean of the correct type and inject it for you.
Inject by name
If you have more than one bean of a given type defined you can request that a bean with a specific name be injected. This bean name must match the id
attribute of the bean’s tag as defined in your BeanProvider
.
[Inject( source="userService" )]
public var service:RemoteObject;
...
// will inject this from BeanProvider
<mx:RemoteObject id="userService" />
Quick Tip.
source
is the default attribute of[Inject]
, so the above tag could also be written as[Inject("userService")
]
Inject bean property
Crux can also inject public bean properties, rather than just the beans themselves using dot notation. In the following example userModel
is the name of a bean, and we are injecting its currentUser
property.
[Inject( source="userModel.currentUser" )]
public var currentUser : User;
If the bean property is bindable and the decorated property is public, you can have Crux create a binding to the source property by adding bind="true"
to the [Inject]
tag:
[Inject( source="userModel.currentUser", bind="true" )]
public var currentUser : User;
you can also inject nested properties, such as:
[Inject( source="userModel.currentUser.firstName" )]
public var firstName : String;
Two way bindings
To set up a reverse binding, so the bean property will receive updates made to the injection target, you can set the twoWay
attribute of the [Inject]
tag to true. This of course requires that the injection target is bindable as well.
[Bindable]
[Inject( source="userModel.currentUser", twoWay="true" )]
public var currentUser:User;
Setter injection
Crux can also inject values into single argument methods. All of the attributes and policies mentioned above apply to setter injection as well, with the exception of twoWay
.
[Inject]
public function setModel( model:UserModel ):void
{
this.model = model;
}
Injection destination
Sometimes it’s useful to define an injection someplace other than directly on a property/method. This is especially true in MXML views, where decorating a child component’s property is not possible. Rather than creating a local variable and binding your component property to it, you can simply use the destination attribute of [Inject]
. If this were defined in an MXML file, it would be wrapped in a Metadata
tag.
[Inject( source="userModel.currentMode", destination="modeViewStack.selectedIndex" )]
Take care to ensure that the injection destination will be created and available by the time your injections are processed.