Skip to content

Instantly share code, notes, and snippets.

@xleon
Last active August 10, 2016 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xleon/83ef21346749fc674a149f310a92b1aa to your computer and use it in GitHub Desktop.
Save xleon/83ef21346749fc674a149f310a92b1aa to your computer and use it in GitHub Desktop.
Service Locator for ActionScript applications
package Core.Utils.ServiceLocation
{
public interface ILocator
{
function RegisterConstant(value:Object, type:Class):void;
function Register(type:Class, contract:Class = null):void;
function RegisterSingleton(type:Class, contract:Class = null):void;
function Get(type:Class):Object;
}
}
package Core.Utils.ServiceLocation
{
public class LazyType
{
private var _type:Class;
private var _contract:Class;
private var _value:*;
public function get value():*
{
if(_value == null)
{
var instance:* = new _type();
if(_contract != null && !(instance is _contract))
throw new Error("type must implement contract");
_value = instance;
}
return _value;
}
public function LazyType(type:Class, contract:Class = null)
{
_type = type;
_contract = contract;
}
}
}
package Core.Utils.ServiceLocation
{
import flash.utils.Dictionary;
public class Locator implements ILocator
{
private var _map:Dictionary;
public function RegisterConstant(value:Object, type:Class):void
{
ValidateType(type);
_map[ type ] = value;
}
public function Register(type:Class, contract:Class = null):void
{
ValidateType(contract || type);
_map[ contract || type ] = type;
}
public function RegisterSingleton(type:Class, contract:Class = null):void
{
ValidateType(contract || type);
_map[ contract || type ] = new LazyType(type, contract);
}
public function Get(type:Class):Object
{
var mappedValue:* = _map[ type ];
if(mappedValue == null)
{
throw new Error("Type not registered");
}
if(mappedValue is type)
{
return mappedValue;
}
if(mappedValue is Class)
{
return new mappedValue();
}
if(mappedValue is LazyType)
{
return LazyType(mappedValue).value;
}
throw new Error("type is registered but something wrong happened. If you got to this Error, you should probably not be using this class :(");
}
private function ValidateType(type:Class):void
{
if(type == null)
throw new ArgumentError("type parameter must not be null");
if(!(type is Class))
throw new ArgumentError("type parameter must be a Class type or an Interface");
if(_map[type] != null)
throw new ArgumentError("type is already registered");
}
// Singleton stuff
private static var blocked:Boolean = true;
private static var _current:Locator;
public static function get Current():ILocator
{
if(_current == null)
{
blocked = false;
_current = new Locator();
blocked = true;
}
return _current;
}
public function Locator()
{
if(blocked)
throw new Error("Singleton cannot be instantiated");
_map = new Dictionary();
}
}
}
var stageInfo:StageInfo = new StageInfo(_mainView.stage);
Locator.Current.RegisterConstant(stageInfo, StageInfo);
Locator.Current.RegisterSingleton(ApplicationViewModel);
Locator.Current.RegisterSingleton(MediaService, IMediaService);
Locator.Current.RegisterSingleton(MultiTrackerService, ITrackerService);
// create a new instance every time IHomeViewModel is required
Locator.Current.Register(HomeViewModel, IHomeViewModel);
// get stuff from the locator
var mediaService:IMediaService = Locator.Current.Get(IMediaService) as IMediaService;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment