Created
April 16, 2015 19:04
-
-
Save nadako/69d833f7e9f031fa692c to your computer and use it in GitHub Desktop.
Simple macro-based dependency injection system based on factory functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import haxe.macro.Expr; | |
import haxe.Constraints.Function; | |
#if macro | |
import haxe.macro.Context; | |
import haxe.macro.Type; | |
using haxe.macro.Tools; | |
#end | |
class DI { | |
var instances:Map<String,Dynamic>; | |
var factories:Map<String,Void->Dynamic>; | |
public function new() { | |
instances = new Map(); | |
factories = new Map(); | |
} | |
public macro function add(self:Expr, factory:ExprOf<Function>):Expr { | |
switch (Context.typeof(factory).follow()) { | |
case TFun(args, ret): | |
var id = ret.toString(); | |
var callArgs = []; | |
for (arg in args) { | |
var id = arg.t.toString(); | |
callArgs.push(macro (@:privateAccess $self._resolve)($v{id})); | |
} | |
return macro (@:privateAccess $self._add)($v{id}, function() return ($factory)($a{callArgs})); | |
default: | |
throw new Error("Factory should be a funtion", factory.pos); | |
} | |
} | |
public macro function run(self:Expr, fn:ExprOf<Function>):Expr { | |
switch (Context.typeof(fn).follow()) { | |
case TFun(args, ret): | |
var callArgs = []; | |
for (arg in args) { | |
var id = arg.t.toString(); | |
callArgs.push(macro (@:privateAccess $self._resolve)($v{id})); | |
} | |
return macro $fn($a{callArgs}); | |
default: | |
throw new Error("fn should be a funtion", fn.pos); | |
} | |
} | |
inline function _add(id:String, factory:Void->Dynamic):Void { | |
if (factories.exists(id)) | |
throw 'Duplicate factory declaration for $id'; | |
factories[id] = factory; | |
} | |
inline function _resolve(id:String):Dynamic { | |
var inst = instances[id]; | |
if (inst == null) { | |
var factory = factories[id]; | |
if (factory == null) | |
throw 'No factory defined for type $id'; | |
inst = instances[id] = factory(); | |
} | |
return inst; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Config { | |
public var appName:String; | |
public function new(appName) this.appName = appName; | |
} | |
class App { | |
var cfg:Config; | |
public function new(cfg:Config) { | |
this.cfg = cfg; | |
} | |
public function startup() { | |
trace("Hello from " + cfg.appName); | |
} | |
} | |
class Main { | |
static function main () { | |
var di = new DI(); | |
di.add(Config.new.bind("MyApp")); | |
di.add(App.new); | |
di.run(function(cfg:Config, app:App) { | |
app.startup(); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment