mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-01-25 22:36:44 +00:00
refactored code
This commit is contained in:
120
lib/src/binding.dart
Normal file
120
lib/src/binding.dart
Normal file
@@ -0,0 +1,120 @@
|
||||
///
|
||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
enum Mode { SIMPLE, INSTANCE, PROVIDER_INSTANCE }
|
||||
|
||||
/// RU: Класс Binding<T> настраивает параметры экземпляра.
|
||||
/// ENG: The Binding<T> class configures the settings for the instance.
|
||||
///
|
||||
class Binding<T> {
|
||||
late Mode _mode;
|
||||
late Type _key;
|
||||
late String _name;
|
||||
T? _instance;
|
||||
T? Function()? _provider;
|
||||
late bool _isSingeltone = false;
|
||||
late bool _isNamed = false;
|
||||
|
||||
Binding() {
|
||||
_mode = Mode.SIMPLE;
|
||||
_key = T;
|
||||
}
|
||||
|
||||
/// RU: Метод возвращает [Mode] экземпляра.
|
||||
/// ENG: The method returns the [Mode] of the instance.
|
||||
///
|
||||
/// return [Mode]
|
||||
Mode get mode => _mode;
|
||||
|
||||
/// RU: Метод возвращает тип экземпляра.
|
||||
/// ENG: The method returns the type of the instance.
|
||||
///
|
||||
/// return [Type]
|
||||
Type get key => _key;
|
||||
|
||||
/// RU: Метод возвращает имя экземпляра.
|
||||
/// ENG: The method returns the name of the instance.
|
||||
///
|
||||
/// return [String]
|
||||
String get name => _name;
|
||||
|
||||
/// RU: Метод проверяет сингелтон экземпляр или нет.
|
||||
/// ENG: The method checks the singleton instance or not.
|
||||
///
|
||||
/// return [bool]
|
||||
bool get isSingeltone => _isSingeltone;
|
||||
|
||||
/// RU: Метод проверяет именован экземпляр или нет.
|
||||
/// ENG: The method checks whether the instance is named or not.
|
||||
///
|
||||
/// return [bool]
|
||||
bool get isNamed => _isNamed;
|
||||
|
||||
/// RU: Добавляет имя для экземляпя [value].
|
||||
/// ENG: Added name for instance [value].
|
||||
///
|
||||
/// return [Binding]
|
||||
Binding<T> withName(String name) {
|
||||
_name = name;
|
||||
_isNamed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Инициализация экземляпяра [value].
|
||||
/// ENG: Initialization instance [value].
|
||||
///
|
||||
/// return [Binding]
|
||||
Binding<T> toInstance(T value) {
|
||||
_mode = Mode.INSTANCE;
|
||||
_instance = value;
|
||||
_isSingeltone = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Инициализация экземляпяра через провайдер [value].
|
||||
/// ENG: Initialization instance via provider [value].
|
||||
///
|
||||
/// return [Binding]
|
||||
Binding<T> toProvide(T Function() value) {
|
||||
_mode = Mode.PROVIDER_INSTANCE;
|
||||
_provider = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Инициализация экземляпяра как сингелтон [value].
|
||||
/// ENG: Initialization instance as a singelton [value].
|
||||
///
|
||||
/// return [Binding]
|
||||
Binding<T> singeltone() {
|
||||
_isSingeltone = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Поиск экземпляра.
|
||||
/// ENG: Resolve instance.
|
||||
///
|
||||
/// return [T]
|
||||
T? get instance => _instance;
|
||||
|
||||
/// RU: Поиск экземпляра.
|
||||
/// ENG: Resolve instance.
|
||||
///
|
||||
/// return [T]
|
||||
T? get provider {
|
||||
if (_isSingeltone) {
|
||||
_instance ??= _provider?.call();
|
||||
return _instance;
|
||||
}
|
||||
return _provider?.call();
|
||||
}
|
||||
}
|
||||
17
lib/src/factory.dart
Normal file
17
lib/src/factory.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
///
|
||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
import 'package:cherrypick/src/scope.dart';
|
||||
|
||||
abstract class Factory<T> {
|
||||
T createInstance(Scope scope);
|
||||
}
|
||||
36
lib/src/helper.dart
Normal file
36
lib/src/helper.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
///
|
||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
import 'package:cherrypick/src/scope.dart';
|
||||
|
||||
Scope? _rootScope;
|
||||
|
||||
class CherryPick {
|
||||
/// RU: Метод открывает главный [Scope].
|
||||
/// ENG: The method opens the main [Scope].
|
||||
///
|
||||
/// return
|
||||
static Scope openRootScope() {
|
||||
_rootScope ??= Scope(null);
|
||||
return _rootScope!;
|
||||
}
|
||||
|
||||
/// RU: Метод закрывает главный [Scope].
|
||||
/// ENG: The method close the main [Scope].
|
||||
///
|
||||
///
|
||||
static void closeRootScope() {
|
||||
if (_rootScope != null) {
|
||||
_rootScope = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
53
lib/src/module.dart
Normal file
53
lib/src/module.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
///
|
||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:cherrypick/src/binding.dart';
|
||||
import 'package:cherrypick/src/scope.dart';
|
||||
|
||||
/// RU: Класс Module является основой для пользовательских модулей.
|
||||
/// Этот класс нужен для инициализации [Scope].
|
||||
///
|
||||
/// RU: The Module class is the basis for custom modules.
|
||||
/// This class is needed to initialize [Scope].
|
||||
///
|
||||
abstract class Module {
|
||||
final Set<Binding> _bindingSet = HashSet();
|
||||
|
||||
/// RU: Метод добавляет в коллекцию модуля [Binding] экземпляр.
|
||||
///
|
||||
/// ENG: The method adds an instance to the collection of the [Binding] module.
|
||||
///
|
||||
/// return [Binding<T>]
|
||||
Binding<T> bind<T>() {
|
||||
final binding = Binding<T>();
|
||||
_bindingSet.add(binding);
|
||||
return binding;
|
||||
}
|
||||
|
||||
/// RU: Метод возвращает коллекцию [Binding] экземпляров.
|
||||
///
|
||||
/// ENG: The method returns a collection of [Binding] instances.
|
||||
///
|
||||
/// return [Set<Binding>]
|
||||
Set<Binding> get bindingSet => _bindingSet;
|
||||
|
||||
/// RU: Абстрактный метод для инициализации пользовательских экземпляров.
|
||||
/// В этом методе осуществляется конфигурация зависимостей.
|
||||
///
|
||||
/// ENG: Abstract method for initializing custom instances.
|
||||
/// This method configures dependencies.
|
||||
///
|
||||
/// return [void]
|
||||
void builder(Scope currentScope);
|
||||
}
|
||||
126
lib/src/scope.dart
Normal file
126
lib/src/scope.dart
Normal file
@@ -0,0 +1,126 @@
|
||||
///
|
||||
/// Copyright 2021 Sergey Penkovsky <sergey.penkovsky@gmail.com>
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:cherrypick/src/binding.dart';
|
||||
import 'package:cherrypick/src/module.dart';
|
||||
|
||||
Scope openRootScope() => Scope(null);
|
||||
|
||||
class Scope {
|
||||
final Scope? _parentScope;
|
||||
|
||||
/// RU: Метод возвращает родительский [Scope].
|
||||
///
|
||||
/// ENG: The method returns the parent [Scope].
|
||||
///
|
||||
/// return [Scope]
|
||||
Scope? get parentScope => _parentScope;
|
||||
|
||||
final Map<String, Scope> _scopeMap = HashMap();
|
||||
|
||||
Scope(this._parentScope);
|
||||
|
||||
final Set<Module> _modulesList = HashSet();
|
||||
|
||||
/// RU: Метод открывает дочерний (дополнительный) [Scope].
|
||||
///
|
||||
/// ENG: The method opens child (additional) [Scope].
|
||||
///
|
||||
/// return [Scope]
|
||||
Scope openSubScope(String name) {
|
||||
if (!_scopeMap.containsKey(name)) {
|
||||
_scopeMap[name] = Scope(this);
|
||||
}
|
||||
return _scopeMap[name]!;
|
||||
}
|
||||
|
||||
/// RU: Метод закрывает дочерний (дополнительный) [Scope].
|
||||
///
|
||||
/// ENG: The method closes child (additional) [Scope].
|
||||
///
|
||||
/// return [Scope]
|
||||
void closeSubScope(String name) {
|
||||
_scopeMap.remove(name);
|
||||
}
|
||||
|
||||
/// RU: Метод инициализирует пользовательские модули в [Scope].
|
||||
///
|
||||
/// ENG: The method initializes custom modules in [Scope].
|
||||
///
|
||||
/// return [Scope]
|
||||
Scope installModules(List<Module> modules) {
|
||||
_modulesList.addAll(modules);
|
||||
modules.forEach((module) => module.builder(this));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Метод удаляет пользовательские модули из [Scope].
|
||||
///
|
||||
/// ENG: This method removes custom modules from [Scope].
|
||||
///
|
||||
/// return [Scope]
|
||||
Scope dropModules() {
|
||||
_modulesList.removeAll(_modulesList);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// RU: Возвращает найденную зависимость, определенную параметром типа [T].
|
||||
/// Выдает [StateError], если зависимость не может быть разрешена.
|
||||
/// Если вы хотите получить [null], если зависимость не может быть найдена,
|
||||
/// то используйте вместо этого [tryResolve]
|
||||
/// return - возвращает объект типа [T] или [StateError]
|
||||
///
|
||||
/// ENG: Returns the found dependency specified by the type parameter [T].
|
||||
/// Throws [StateError] if the dependency cannot be resolved.
|
||||
/// If you want to get [null] if the dependency cannot be found then use [tryResolve] instead
|
||||
/// return - returns an object of type [T] or [StateError]
|
||||
///
|
||||
T resolve<T>({String? named}) {
|
||||
var resolved = tryResolve<T>(named: named);
|
||||
if (resolved != null) {
|
||||
return resolved;
|
||||
} else {
|
||||
throw StateError(
|
||||
'Can\'t resolve dependency `$T`. Maybe you forget register it?');
|
||||
}
|
||||
}
|
||||
|
||||
/// RU: Возвращает найденную зависимость типа [T] или null, если она не может быть найдена.
|
||||
/// ENG: Returns found dependency of type [T] or null if it cannot be found.
|
||||
///
|
||||
T? tryResolve<T>({String? named}) {
|
||||
// 1 Поиск зависимости по всем модулям текущего скоупа
|
||||
if (_modulesList.isNotEmpty) {
|
||||
for (var module in _modulesList) {
|
||||
for (var binding in module.bindingSet) {
|
||||
if (binding.key == T &&
|
||||
((!binding.isNamed && named == null) ||
|
||||
(binding.isNamed && named == binding.name))) {
|
||||
switch (binding.mode) {
|
||||
case Mode.INSTANCE:
|
||||
return binding.instance;
|
||||
case Mode.PROVIDER_INSTANCE:
|
||||
return binding.provider;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2 Поиск зависимостей в родительском скоупе
|
||||
return _parentScope != null ? _parentScope!.tryResolve(named: named) : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user