Dependency injection in flex
Finally I played with inversion of control in flex. It was only one thing that I missed in big actionscript application. Here is sample dependencytest.zip
Start conditions
To implement dependency injection need a way to access to each class in application in order to define if it marked with metadata or not. Metaprogramming way can simplify, automate usage of util. But here is one problem. How to get access to all classes in application. Here could be 3 ways:
* Write list of classes in code manually. The most easy and lightweight solution. But have small inconvenience so need add each new class to list.
* Write configuration files and put there names of classes that need to instantiate. Most complex for use but not hard to implement way. It also gives few excess abilities.
* Add ability to load current swf into itself and parse it in order to find included classes. Most complex to implement and application have some delay in start. In other side it is easy to use that solution.
I tried 3rd one because it easy to use by developer and most complex work is already done. So loading and parsing swf are possible and available in open source libraries. See previous post. To marking class as bean metadata was used. Using metadata gives such easy flexibility.
If you found 3rd way isn’t good for your application you still can use 1st way with declaring classes manually.
Make it easy
I decided not to write complex system for dependency injection. So the main needed requirement is having initialized beans with injected dependencies. As for me that is enough for most cases. Here is few simple steps to start:
1. To mark class as singleton bean just need to put “Dependency” metadata over the class definition.
[Dependency]
public class AccountModel
Don’t forget to include this custom metadata into flex configuration file: flex-config.xml
2. To have a value of bean passed to your class instance need to declare public property or accessor with the same name. For example you need inject AccountModel then define accountModel accessor:
private var _accountModel:AccountModel;
public function set accountModel(value:AccountModel):void {
_accountModel = value;
}
3. If you want to create instance and setup it with all available beans dependencies then use:
var command:BootCommand = dependencyUtil.createInScope(BootCommand) as BootCommand;
Power of simplicity
You may notice that here is no way for defining two beans of same type or set a custom name to bean. As for me it’s not a big problem and most of goals still can be achieved via following name convention. Where this dependency injection is useful:
1. Defining a single instance per application of some class. It is realy a pain to access application models without IoC. You have to make all your models classes as singleton or put them into static/singleton facade. And manually retrieve model instances at the beginning of code or class. Dependency injection allow easy to mark class to export as singleton and inject it instance to other singletons at startup.
2. Create new controllers (in case you are using Cairngorm or similar architecture) with injecting dependencies. You can skip declaring models or delegates values in your controllers. Usually it is done via ServiceLocator or ModelLocator. You only need to override command initialization way so using dependencyUtil.createInScope instead of new Command().
Conclusion
My sample code adds to project 60KB when used. But if you get rid out of complex swf parsing then size of util could be 5KB! So it can be small and still power. Size of application still matter for web applications. Util metadata in actionscript instead of configuration files. That gives simplicity for user but maybe restrict in some future features.
Comments(2)

