Skip to content

Instantly share code, notes, and snippets.

@neilmanuell
Last active December 29, 2015 06:08
Show Gist options
  • Save neilmanuell/7626409 to your computer and use it in GitHub Desktop.
Save neilmanuell/7626409 to your computer and use it in GitHub Desktop.
RL1.5 ConfigurableModules
public class ApplicationContext extends ConfigurableContext
{
public function PreloaderContext( contextView:DisplayObjectContainer )
{
super( contextView );
}
override public function startup():void
{
loadLocalSettings()
}
private function loadLocalSettings():void
{
var settingsLoader:XMLLoader = new XMLLoader("assets/bootstrap-settings.xml", { name:"bootstrap-settings" } ) ;
settingsLoader.addEventListener(LoaderEvent.COMPLETE, loader_complete);
settingsLoader.addEventListener(LoaderEvent.ERROR, loader_error);
settingsLoader.load();
}
private function loader_error(e:LoaderEvent):void
{
throw(new Error("Error loading initial setup from assets/bootstrap-settings.xml: " + e.data));
}
private function loader_complete(e:LoaderEvent):void
{
// continue with configuration (initialize).
super.startup();
}
override protected function initialise():void
{
trace( "PreloaderContext.initialise" );
// context (parent injector) extended, but the configure method NOT called
extend(
BootstrapSettingsConfig,
TraceLoggingConfig ,
FileLoggingConfig ,
LoggingLevelConfig ,
... );
// module (child injector) extended, and the configure method IS called
injector.mapSingleton(ConfigurableModule);
const module:ConfigurableModule = injector.getInstance(ConfigurableModule);
module.addEventListener( ModuleEvent.COMPLETE, bootstrapComplete);
module.extend(
LoaderServiceConfig,
...).configure();
}
private function bootstrapComplete( e:Event ):void
{
trace( "PreloaderContext.startupComplete > e : " + e );
// application configured;
configure();
commandMap.execute( RequestData );
}
}
public class ConfigurableContext extends Context implements IConfigurableModule
{
private var _configManager:IConfigurableModule;
public function ConfigurableContext( contextView:DisplayObjectContainer, autoStartup:Boolean )
{
super( contextView, autoStartup );
}
protected function get configManager():IConfigurableModule
{
return _configManager ||= new ConfigurationManager( injector );
}
override protected function mapInjections():void
{
super.mapInjections();
injector.mapValue( IConfigurableModule ,configManager );
}
protected function initialise( ):void
{
}
public function extend( ...classRefs ):IConfigurableModule
{
configManager.extend.apply( null, classRefs );
return this;
}
public function configure():void
{
configManager.configure();
}
}
public class ConfigurableModule extends EventDispatcher implements IConfigurableModule
{
private var _configManager:IConfigurableModule;
public function ConfigurableModule( injector:IInjector )
{
mapInjections( injector.createChild() );
}
private function mapInjections( injector:IInjector ):void
{
injector.mapValue( IInjector, injector );
injector.mapSingleton( ConfigurationManager );
_configManager = injector.getInstance( ConfigurationManager );
// override injections such as ICommandMap
initialise( );
}
protected function initialise( ):void
{
}
public function extend( ...classRefs ):IConfigurableModule
{
_configManager.extend.apply( null, classRefs );
return this;
}
public function configure():void
{
_configManager.configure();
}
}
public class ConfigurationManager implements IConfigurableModule
{
private var _configs:Vector.<*> = new Vector.<*>();
public function ConfigurationManager( injector:IInjector )
{
_injector = injector;
}
private var _injector:IInjector;
public function extend( ...classRefs ):IConfigurableModule
{
_configs = _configs.concat( Vector.<*>( classRefs ) );
return this;
}
public function configure():void
{
_configs.fixed = true;
for each( var o:* in _configs )
{
if ( o is Class )
{
_injector.instantiate( o as Class );
}
else if ( o is IConfig )
{
_injector.injectInto( o );
}
if ( o.hasOwnProperty( "configure" ) && o.configure is Function )
{
o.configure();
}
}
_configs.fixed = false;
_configs.length = 0;
}
}
public interface IConfigurableModule
{
function extend( ...classRefs ):IConfigurableModule
function configure( ):void
}
public class LoaderServiceConfig
{
[Inject]
public var injector:IInjector;
public function configure():void
{
// mappings to be sandboxed in the childInjector
injector.mapSingletonOf( ILoaderService, LoaderService );
// mappings to be available to parent and child.
const service:LoaderService = injector.getInstance( ILoaderService );
const parent:IInjector = (injector.parent == null ) ? injector : injector.parent;
injector.mapValue( IBitmapDataProvider, service );
injector.mapValue( IBinaryDataProvider, service );
injector.mapValue( IXMLProvider, service );
injector.mapValue( IMP3Provider, service );
injector.mapValue( ISWFProvider, service );
}
}
@neilmanuell
Copy link
Author

  • changes name from IConfigurableContext to IConfigurableModule
  • extracts configuration logic into ConfigurationManager to allow configuration at any stage in the injector's scope
  • the ConfigurableContext and the ConfigurableModule are both almost identical apart from the inheritance chain.
  • the ConfigurableContext will hold the Application configuration and the parent injector.
  • the ConfigurableModule will hold the Bootstrap configuration and be the child injector.
  • the LoaderServiceConfig shows how actors can be injected into the child injector for sandboxed access, or in the parent injector, allowing access by both.
  • mappings into the child can be accessed only from the child.
  • mappings into the parent can be accessed by both parent and child
  • mappings can be overidden in the child.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment