1 /** 2 * Модуль предоставляет объекты и методы для работы с именованным внедрением зависимостей (DI) 3 * 4 * Copyright: (c) 2015-2017, Milofon Project. 5 * License: Subject to the terms of the BSD license, as written in the included LICENSE.txt file. 6 * Authors: Maksim Galanin 7 */ 8 module dango.system.container.named; 9 10 private 11 { 12 import poodinis; 13 } 14 15 /** 16 * Контейнер для управления именованных зависимостей 17 * 18 * При помощи данного контейнера можно зарегистрировать именованную зависимось определенного типа. 19 * Имена уникальны в рамках одного типа 20 */ 21 class NamedContainer 22 { 23 private Registration[string][TypeInfo] registrations; 24 25 /** 26 * Регистрация зависимости 27 * 28 * Params: 29 * 30 * reg = Объект регистрации типа 31 * name = Имя (метка) типа 32 */ 33 void register(Registration reg, string name) 34 { 35 registrations[reg.registeredType][name] = reg; 36 } 37 38 /** 39 * Получение объекта из именованного контейнера по имени 40 * 41 * Метод не учитывает опции, которые есть в оригинальном методе DependencyContainer 42 * 43 * Params: 44 * 45 * name = Имя требуемой зависимости 46 * 47 * See_Also: poodinis.container: DependencyContainer 48 */ 49 RegistrationType resolve(RegistrationType)(string name) 50 { 51 TypeInfo resolveType = typeid(RegistrationType); 52 53 auto candidates = resolveType in registrations; 54 if (!candidates) 55 throw new ResolveException("Type not registered.", resolveType); 56 57 if (auto r = name in *candidates) 58 { 59 auto autowireContext = new AutowireInstantiationContext(); 60 autowireContext.autowireInstance = true; 61 return cast(RegistrationType)(*r).getInstance(autowireContext); 62 } 63 64 return null; 65 } 66 } 67 68 69 /** 70 * Метод расширяет поведение DependencyContainer при помощи NamedContainer и добавляет возможность регистрировать именованные зависимости 71 * 72 * Params: 73 * 74 * container = Контейнер управляющий зависимостями 75 * name = Имя(метка) типа 76 * options = Опции для регистрации зависимости 77 * 78 * Returns: Объект регистрации 79 */ 80 Registration registerByName(SuperType, ConcreteType: SuperType)(shared(DependencyContainer) container, string name, RegistrationOption options = RegistrationOption.none) 81 { 82 NamedContainer nc = container.resolve!NamedContainer(ResolveOption.registerBeforeResolving); 83 Registration reg = container.register!(SuperType, ConcreteType)(options); 84 nc.register(reg, name); 85 return reg; 86 } 87 88 89 /** 90 * Метод расширяет поведение DependencyContainer при помощи NamedContainer и добавляет возможность создать объект указав тип помеченный именем 91 * 92 * Params: 93 * 94 * container = Контейнер зависимостей 95 * name = Имя(метка) типа 96 * 97 * Returns: Объект зарегистрированного типа 98 */ 99 RegistrationType resolveByName(RegistrationType)(shared(DependencyContainer) container, string name) 100 { 101 NamedContainer nc = container.resolve!NamedContainer(ResolveOption.registerBeforeResolving); 102 return nc.resolve!RegistrationType(name); 103 } 104 105 106 /** 107 * Метод расширяет поведение DependencyContainer при помощи NamedContainer и добавляет возможность создать объект указав тип помеченный именем 108 * 109 * Params: 110 * 111 * container = Контейнер зависимостей 112 * name = Имя(метка) типа 113 * 114 * Returns: Объект требуемого типа 115 */ 116 QualifierType resolveByName(RegistrationType, QualifierType : RegistrationType)(shared(DependencyContainer) container, string name) 117 { 118 return cast(QualifierType) resolveByName!RegistrationType(container, name); 119 } 120