Dart 控制反转之IOC

控制反转容器(IOC)

依赖于反射库 dart:mirrors

import 'dart:mirrors';

///Inversion of control container
class Ioc
{
    final List _types = [];
    final Map _names = {};
    final Map _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 positionalArguments = const [], Map 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 positionalArguments = const [], Map namedArguments})
    {
        _throwNoHasName(name);

        var type = getType(name);

        return getInstance(type);
    }

    Type getType(String name)
    {
        return _names[name];
    }

    List getAllType()
    {
        return _types;
    }

    Map getAllName()
    {
        return _names;
    }

    Map 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 positionalArguments = const [], Map 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 positionalArguments = const [], Map 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");
        }
    }
}

你可能感兴趣的:(Dart 控制反转之IOC)