控制反转容器(IOC)
依赖于反射库 dart:mirrors
import 'dart:mirrors';
///Inversion of control container
class Ioc
{
final List<Type> _types = [];
final Map<String, Type> _names = {};
final Map<Type, InstanceMirror> _instances = {};
///Register [type], optional [name]
void registerType(Type type, {String name})
{
if(type == dynamic) {
throw Exception('Dynamic type cannot be registered to container');
}
var mirror = reflectClass(type);
if(mirror is FunctionTypeMirror) {
throw Exception("Typedef type '$type' cannot be registered to container");
}
if(!mirror.hasReflectedType) {
throw Exception("Type '$type' is not a reflected type");
}
if (mirror.isEnum) {
throw Exception("Enum type '$type' cannot be registered to container");
}
if(mirror.isAbstract) {
throw Exception("Type '$type' cannot be abstract class");
}
if(name == null || name == '') {
name = type.toString();
}
if(hasName(name)) {
throw Exception("Name '$name' of type '$type' already exists in the container");
}
_names[name] = type;
if(!hasType(type)) {
_types.add(type);
}
}
///Register an existing [instance], optional [name]
void registerInstance(dynamic instance, {String name})
{
if(instance is Type || instance is Function) {
throw Exception("Instance '$instance' is not an instance of a class");
}
var mirror = reflect(instance);
var type = mirror.reflectee.runtimeType;
if(name == null || name == '') {
name = type.toString();
}
_throwHasName(type, name);
_types.add(type);
_names[name] = type;
_instances[type] = mirror;
}
///Set the [name] of the [type]
void setName(Type type, String name)
{
_throwNoHasType(type);
_throwHasName(type, name);
_names[name] = type;
}
///Get instance of the [type]
dynamic getInstance(Type type, {Symbol constructor = Symbol.empty, bool singleton = true, bool reflectee = true, List<dynamic> positionalArguments = const [], Map<Symbol, dynamic> namedArguments})
{
_throwNoHasType(type);
if(!singleton || !hasInstance(type)) {
_instances[type]= reflectClass(type).newInstance(constructor, positionalArguments, namedArguments);
}
return reflectee ? _instances[type].reflectee : _instances[type];
}
///Get instance by the [name]
dynamic getInstanceByName(String name, {Symbol constructor = Symbol.empty, bool existed = true, bool reflectee = true, List<dynamic> positionalArguments = const [], Map<Symbol, dynamic> namedArguments})
{
_throwNoHasName(name);
var type = getType(name);
return getInstance(type);
}
Type getType(String name)
{
return _names[name];
}
List<Type> getAllType()
{
return _types;
}
Map<String, Type> getAllName()
{
return _names;
}
Map<Type, dynamic> getAllInstance()
{
return _instances;
}
bool hasType(Type type)
{
return _types.contains(type);
}
bool hasName(String name)
{
return _names.containsKey(name);
}
bool hasInstance(Type type)
{
return _instances.containsKey(type);
}
dynamic invokeMethod(Type type, Symbol method, {bool isStatic = false, List<dynamic> positionalArguments = const [], Map<Symbol, dynamic> namedArguments})
{
_throwNoHasType(type);
if(isStatic) {
return reflectClass(type).invoke(method, positionalArguments, namedArguments);
}
_throwNoHasInstance(type);
return _instances[type].invoke(method, positionalArguments, namedArguments);
}
dynamic invokeMethodByName(String name, Symbol method, {bool isStatic = false, List<dynamic> positionalArguments = const [], Map<Symbol, dynamic> namedArguments})
{
_throwNoHasName(name);
var type = getType(name);
return invokeMethod(type, method, isStatic: isStatic, positionalArguments: positionalArguments, namedArguments: namedArguments);
}
void _throwNoHasName(String name)
{
if(!hasName(name)) {
throw Exception("Name '$name' does not exist in the container");
}
}
void _throwHasName(Type type, String name)
{
if(hasName(name)) {
throw Exception("Name '$name' of type '$type' already exists in the container");
}
}
void _throwNoHasType(Type type)
{
if(!hasType(type)) {
throw Exception("Type '$type' is not registered in the container");
}
}
void _throwNoHasInstance(Type type)
{
if(!hasInstance(type)) {
throw Exception(" Instance of type '$type' does not exists in the container");
}
}
}