This isn't really an answer, since you don't state what's going wrong, but some general advice. Mostly, I'd avoid new Symbol()
and mirrors if you can easily avoid them, and in this case you can.
First, you should figure out if you want to register module instances or produce instances on demand, you probably don't want both like you are here. If you register an instance, then can't you just reuse that instance? Does start()
need to produce new instances as part of its spec? You turn around and try to make sure that an instance isn't already running anyway.
If you really do need to produce instances, a simple factory function will eliminate the need for mirrors. So instead of:
core.register(new ToDos());
You write:
core.register('ToDos', () => new ToDos());
If you still want to use mirrors, you can clean up the use of new Symbol()
. Here's some recommendations:
- Don't use Symbols as keys unless you're really getting them from reflective APIs like mirrors and noSuchMethod in the first place. Just use the String name or maybe the runtimeType. In your case you're mixing Symbols and Strings as keys in your
_registeredModules
map, which is probably causing some bugs, like modules will never appear to be registered. (are you testing in checked mode?)
- Don't use
new Symbol('name')
, use const Symbol('name')
Don't use InstanceMirror.invoke, getField, or setField when you can just call the method directly. In your code you can replace
moduleInstance.invoke(new Symbol("start"), [options]);
with
moduleInstance.reflectee.start(options);
- Factories aren't evil. It'd be nice to invoke a constructor from a type instance, but until then registering a factory is pretty lightweight in Dart.
Here's your code with those suggestions:
typedef Object Factory(Sandbox sandbox);
final Map<Symbol, Factory> _registeredModules = new Map<Type, Factory>();
register(Type type, Factory factory) {
if (_registeredModules.containsKey(type)) {
throw new StateError("Module $type already registered!");
}
_registeredModules[type] = factory;
}
start(Type type, options) {
if (!_registeredModules.containsKey(type)) {
throw new StateError("Module $type not registered!");
}
if (_runningModules.containsKey(type)) {
throw new StateError("Module $type already running!");
}
Sandbox sandbox = new Sandbox(this.mediator);
var module = _runningModules[type](sandbox)..start(options);
_runningModules[type] = module;
}