Skip to content

Instantly share code, notes, and snippets.

@JoeRobich JoeRobich/HashMap.as
Created Sep 14, 2012

Embed
What would you like to do?
ActionScript IoC
package com.thedevstop.utilities
{
import flash.utils.Dictionary;
public class HashMap extends Dictionary
{
public function get(key:*):*
{
return this[key];
}
public function set(key:*, value:*):void
{
this[key] = value;
}
public function remove(key:*):void
{
delete this[key];
}
public function contains(key:*):Boolean
{
return get(key) !== undefined;
}
public function get keys():Array
{
var keys:Array = [];
for (var key:* in this)
keys.push(key);
return keys;
}
public function get values():Array
{
var values:Array = [];
for (var key:* in keys)
values.push(get(key));
return values;
}
public function clear():void
{
for (var key:* in keys)
remove(key);
}
}
}
package com.thedevstop.utilities
{
import flash.utils.describeType;
import flash.utils.Dictionary;
import flash.utils.getDefinitionByName;
public class Injector
{
private var _providers:HashMap = new HashMap();
public function Injector()
{
}
public function bind(type:*, concrete:*):void
{
if (type is String)
type = getDefinitionByName(type);
if (!(type is Class))
throw new Error("type must be either a Class or a Qualified Class Name.");
if (type != String &&
concrete is String)
concrete = getDefinitionByName(concrete);
if (concrete is Class)
_providers.set(type, function() { return resolveByClass(concrete); } );
else
_providers.set(type, function() { return concrete; } );
}
public function resolve(type:*):*
{
if (type is String)
type = getDefinitionByName(type);
if (!(type is Class))
throw new Error("type must be either a Class or a Qualified Class Name.");
if (_providers.contains(type))
return _providers.get(type)();
return resolveByClass(type);
}
private function resolveByClass(type:Class):*
{
if (type.instance !== undefined)
return type.instance;
var parameters:Array = [];
var description:XML = describeType(type);
for each (var parameter:XML in description.factory.constructor.parameter)
{
if (parameter.@optional.toString() != "false")
break;
parameters.push(resolve(parameter.@type.toString()));
}
return createObject(type, parameters);
}
private function createObject(type:Class, parameters:Array):*
{
switch (parameters.length)
{
case 0 : return new type();
case 1 : return new type(parameters[0]);
case 2 : return new type(parameters[0], parameters[1]);
case 3 : return new type(parameters[0], parameters[1], parameters[2]);
case 4 : return new type(parameters[0], parameters[1], parameters[2], parameters[3]);
case 5 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4]);
case 6 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5]);
case 7 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6]);
case 8 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7]);
case 9 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8]);
case 10 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9]);
case 11 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10]);
case 12 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11]);
case 13 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11], parameters[12]);
case 14 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11], parameters[12], parameters[13]);
case 15 : return new type(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5], parameters[6], parameters[7], parameters[8], parameters[9], parameters[10], parameters[11], parameters[12], parameters[13], parameters[14]);
default : throw new Error("Too many constructor parameters for createObject");
}
}
}
}
@druttka

This comment has been minimized.

Copy link

commented Sep 14, 2012

Nice, looks like this would support some common use cases. A few thoughts:

  • In get values(), loop through this instead of through keys. Otherwise you loop twice - once to get the copy and again to iterate over it.
  • Naming Nitpick, I probably would have gone _bindings, _registrations, maybe something else over _providers. Note: Providers was used a lot in a past project to mean something very different, which might be why I am avoiding it here.
  • Some duplication at the top of bind and top of resolve. Could the logic of checking for string and turning that into Class be moved out?
  • Is line 50-51 support for singletons?!
  • What if we actually want to specify what to use for the optional parameters?
  • Let me encourage you to kick up asunit (let's not bring flex into this?) when this goes "official" =p
@druttka

This comment has been minimized.

Copy link

commented Sep 14, 2012

Preemptive strike: I haven't had my morning coffee, so I hope the above made any bit of sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.