美文网首页
Dart 控制反转之IOC

Dart 控制反转之IOC

作者: 小鱼宠ZZ | 来源:发表于2020-02-14 15:31 被阅读0次
控制反转容器(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");
        }
    }
}

相关文章

网友评论

      本文标题:Dart 控制反转之IOC

      本文链接:https://www.haomeiwen.com/subject/oyzdfhtx.html