2018-07-10 18:18:10 +00:00
|
|
|
import 'exception.dart';
|
|
|
|
import 'reflector.dart';
|
|
|
|
|
|
|
|
class Container {
|
|
|
|
final Reflector reflector;
|
|
|
|
final Map<Type, dynamic> _singletons = {};
|
|
|
|
|
|
|
|
Container(this.reflector);
|
|
|
|
|
|
|
|
T make<T>(Type type) {
|
|
|
|
if (_singletons.containsKey(type)) {
|
|
|
|
return _singletons[type] as T;
|
|
|
|
} else {
|
|
|
|
var reflectedType = reflector.reflectType(type);
|
|
|
|
var positional = [];
|
|
|
|
var named = <String, dynamic>{};
|
|
|
|
|
|
|
|
if (reflectedType is ReflectedClass) {
|
2018-08-11 19:07:35 +00:00
|
|
|
bool isDefault(String name) {
|
|
|
|
return name.isEmpty || name == reflectedType.name;
|
|
|
|
}
|
|
|
|
|
2018-07-10 18:18:10 +00:00
|
|
|
var constructor = reflectedType.constructors.firstWhere(
|
2018-08-11 19:07:35 +00:00
|
|
|
(c) => isDefault(c.name),
|
|
|
|
orElse: () => throw new ReflectionException(
|
|
|
|
'${reflectedType.name} has no default constructor, and therefore cannot be instantiated.'));
|
2018-07-10 18:18:10 +00:00
|
|
|
|
|
|
|
for (var param in constructor.parameters) {
|
2018-08-11 19:07:35 +00:00
|
|
|
var value = make(param.type.reflectedType);
|
2018-07-10 18:18:10 +00:00
|
|
|
|
|
|
|
if (param.isNamed) {
|
|
|
|
named[param.name] = value;
|
|
|
|
} else {
|
|
|
|
positional.add(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-11 19:07:35 +00:00
|
|
|
return reflectedType.newInstance(
|
|
|
|
isDefault(constructor.name) ? '' : constructor.name,
|
|
|
|
positional,
|
|
|
|
named, []);
|
2018-07-10 18:18:10 +00:00
|
|
|
} else {
|
|
|
|
throw new ReflectionException(
|
|
|
|
'$type is not a class, and therefore cannot be instantiated.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void singleton(Object object, {Type as}) {
|
|
|
|
if (_singletons.containsKey(as ?? object.runtimeType)) {
|
2018-08-11 19:07:35 +00:00
|
|
|
throw new StateError(
|
|
|
|
'This container already has a singleton for ${as ?? object.runtimeType}.');
|
2018-07-10 18:18:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_singletons[as ?? object.runtimeType] = object;
|
|
|
|
}
|
|
|
|
}
|