mirror of
https://github.com/pese-git/cherrypick.git
synced 2026-05-16 10:10:43 +00:00
feat(benchmark_di): add resolve phases, eager/lazy scenarios, and adapter parity
This commit is contained in:
@@ -59,11 +59,16 @@ class UniversalChainModule extends Module {
|
||||
|
||||
switch (scenario) {
|
||||
case UniversalScenario.register:
|
||||
// Simple singleton registration.
|
||||
bind<UniversalService>()
|
||||
.toProvide(
|
||||
() => UniversalServiceImpl(value: 'reg', dependency: null))
|
||||
.singleton();
|
||||
if (bindingMode == UniversalBindingMode.lazySingletonStrategy) {
|
||||
bind<UniversalService>()
|
||||
.toProvide(
|
||||
() => UniversalServiceImpl(value: 'reg', dependency: null))
|
||||
.singleton();
|
||||
} else {
|
||||
bind<UniversalService>()
|
||||
.toInstance(
|
||||
UniversalServiceImpl(value: 'reg', dependency: null));
|
||||
}
|
||||
break;
|
||||
case UniversalScenario.named:
|
||||
// Named factory registration for two distinct objects.
|
||||
@@ -76,6 +81,8 @@ class UniversalChainModule extends Module {
|
||||
break;
|
||||
case UniversalScenario.chain:
|
||||
// Chain of nested services, with dependency on previous level by name.
|
||||
UniversalService? lastEagerInstance;
|
||||
final Map<String, UniversalService> eagerInstances = {};
|
||||
for (var chainIndex = 0; chainIndex < chainCount; chainIndex++) {
|
||||
for (var levelIndex = 0; levelIndex < nestingDepth; levelIndex++) {
|
||||
final chain = chainIndex + 1;
|
||||
@@ -84,6 +91,17 @@ class UniversalChainModule extends Module {
|
||||
final depName = '${chain}_$level';
|
||||
switch (bindingMode) {
|
||||
case UniversalBindingMode.singletonStrategy:
|
||||
final instance = UniversalServiceImpl(
|
||||
value: depName,
|
||||
dependency: eagerInstances[prevDepName],
|
||||
);
|
||||
bind<UniversalService>()
|
||||
.toInstance(instance)
|
||||
.withName(depName);
|
||||
eagerInstances[depName] = instance;
|
||||
lastEagerInstance = instance;
|
||||
break;
|
||||
case UniversalBindingMode.lazySingletonStrategy:
|
||||
bind<UniversalService>()
|
||||
.toProvide(() => UniversalServiceImpl(
|
||||
value: depName,
|
||||
@@ -116,15 +134,19 @@ class UniversalChainModule extends Module {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Регистрация алиаса без имени (на последний элемент цепочки)
|
||||
final depName = '${chainCount}_$nestingDepth';
|
||||
bind<UniversalService>()
|
||||
.toProvide(
|
||||
() => currentScope.resolve<UniversalService>(named: depName))
|
||||
.singleton();
|
||||
// Register unnamed alias for the last chain element.
|
||||
if (bindingMode == UniversalBindingMode.lazySingletonStrategy) {
|
||||
final depName = '${chainCount}_$nestingDepth';
|
||||
bind<UniversalService>()
|
||||
.toProvide(
|
||||
() => currentScope.resolve<UniversalService>(named: depName))
|
||||
.singleton();
|
||||
} else if (lastEagerInstance != null) {
|
||||
bind<UniversalService>().toInstance(lastEagerInstance);
|
||||
}
|
||||
break;
|
||||
case UniversalScenario.override:
|
||||
// handled at benchmark level, но алиас нужен прямо в этом scope!
|
||||
// Handled at benchmark level, but alias is needed directly in this scope.
|
||||
final depName = '${chainCount}_$nestingDepth';
|
||||
bind<UniversalService>()
|
||||
.toProvide(
|
||||
@@ -189,7 +211,7 @@ class CherrypickDIAdapter extends DIAdapter<Scope> {
|
||||
await CherryPick.closeRootScope();
|
||||
_scope = null;
|
||||
}
|
||||
// SubScope teardown не требуется
|
||||
// SubScope teardown is handled by the parent scope.
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -4,14 +4,14 @@ import 'package:benchmark_di/scenarios/universal_service.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'di_adapter.dart';
|
||||
|
||||
/// Универсальный DIAdapter для GetIt c поддержкой scopes и строгой типизацией.
|
||||
/// DIAdapter for GetIt with scope support and strict typing.
|
||||
class GetItAdapter extends DIAdapter<GetIt> {
|
||||
late GetIt _getIt;
|
||||
final String? _scopeName;
|
||||
final bool _isSubScope;
|
||||
bool _scopePushed = false;
|
||||
|
||||
/// Основной (root) и subScope-конструкторы.
|
||||
/// Root and subScope constructors.
|
||||
GetItAdapter({GetIt? instance, String? scopeName, bool isSubScope = false})
|
||||
: _scopeName = scopeName,
|
||||
_isSubScope = isSubScope {
|
||||
@@ -23,7 +23,7 @@ class GetItAdapter extends DIAdapter<GetIt> {
|
||||
@override
|
||||
void setupDependencies(void Function(GetIt container) registration) {
|
||||
if (_isSubScope) {
|
||||
// Создаём scope через pushNewScope с init
|
||||
// Create scope via pushNewScope with init
|
||||
_getIt.pushNewScope(
|
||||
scopeName: _scopeName,
|
||||
init: (getIt) => registration(getIt),
|
||||
@@ -41,7 +41,7 @@ class GetItAdapter extends DIAdapter<GetIt> {
|
||||
|
||||
@override
|
||||
Future<T> resolveAsync<T extends Object>({String? named}) async =>
|
||||
_getIt<T>(instanceName: named);
|
||||
_getIt.getAsync<T>(instanceName: named);
|
||||
|
||||
@override
|
||||
void teardown() {
|
||||
@@ -92,8 +92,13 @@ class GetItAdapter extends DIAdapter<GetIt> {
|
||||
}
|
||||
break;
|
||||
case UniversalScenario.register:
|
||||
getIt.registerSingleton<UniversalService>(
|
||||
UniversalServiceImpl(value: 'reg', dependency: null));
|
||||
if (bindingMode == UniversalBindingMode.lazySingletonStrategy) {
|
||||
getIt.registerLazySingleton<UniversalService>(
|
||||
() => UniversalServiceImpl(value: 'reg', dependency: null));
|
||||
} else {
|
||||
getIt.registerSingleton<UniversalService>(
|
||||
UniversalServiceImpl(value: 'reg', dependency: null));
|
||||
}
|
||||
break;
|
||||
case UniversalScenario.named:
|
||||
getIt.registerFactory<UniversalService>(
|
||||
@@ -120,6 +125,17 @@ class GetItAdapter extends DIAdapter<GetIt> {
|
||||
instanceName: depName,
|
||||
);
|
||||
break;
|
||||
case UniversalBindingMode.lazySingletonStrategy:
|
||||
getIt.registerLazySingleton<UniversalService>(
|
||||
() => UniversalServiceImpl(
|
||||
value: depName,
|
||||
dependency: level > 1
|
||||
? getIt<UniversalService>(instanceName: prevDepName)
|
||||
: null,
|
||||
),
|
||||
instanceName: depName,
|
||||
);
|
||||
break;
|
||||
case UniversalBindingMode.factoryStrategy:
|
||||
getIt.registerFactory<UniversalService>(
|
||||
() => UniversalServiceImpl(
|
||||
@@ -154,9 +170,15 @@ class GetItAdapter extends DIAdapter<GetIt> {
|
||||
if (scenario == UniversalScenario.chain ||
|
||||
scenario == UniversalScenario.override) {
|
||||
final depName = '${chainCount}_$nestingDepth';
|
||||
getIt.registerSingleton<UniversalService>(
|
||||
getIt<UniversalService>(instanceName: depName),
|
||||
);
|
||||
if (bindingMode == UniversalBindingMode.lazySingletonStrategy) {
|
||||
getIt.registerLazySingleton<UniversalService>(
|
||||
() => getIt<UniversalService>(instanceName: depName),
|
||||
);
|
||||
} else {
|
||||
getIt.registerSingleton<UniversalService>(
|
||||
getIt<UniversalService>(instanceName: depName),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,14 +4,11 @@ import 'package:benchmark_di/scenarios/universal_service.dart';
|
||||
import 'package:kiwi/kiwi.dart';
|
||||
import 'di_adapter.dart';
|
||||
|
||||
/// DIAdapter-для KiwiContainer с поддержкой universal benchmark сценариев.
|
||||
/// DIAdapter for KiwiContainer with universal benchmark scenario support.
|
||||
class KiwiAdapter extends DIAdapter<KiwiContainer> {
|
||||
late KiwiContainer _container;
|
||||
// ignore: unused_field
|
||||
final bool _isSubScope;
|
||||
|
||||
KiwiAdapter({KiwiContainer? container, bool isSubScope = false})
|
||||
: _isSubScope = isSubScope {
|
||||
KiwiAdapter({KiwiContainer? container, bool isSubScope = false}) {
|
||||
_container = container ?? KiwiContainer();
|
||||
}
|
||||
|
||||
@@ -57,6 +54,8 @@ class KiwiAdapter extends DIAdapter<KiwiContainer> {
|
||||
final depName = '${chain}_$level';
|
||||
switch (bindingMode) {
|
||||
case UniversalBindingMode.singletonStrategy:
|
||||
case UniversalBindingMode.lazySingletonStrategy:
|
||||
// Kiwi's registerSingleton is lazy (factory-based, cached on first resolve)
|
||||
container.registerSingleton<UniversalService>(
|
||||
(c) => UniversalServiceImpl(
|
||||
value: depName,
|
||||
@@ -75,7 +74,7 @@ class KiwiAdapter extends DIAdapter<KiwiContainer> {
|
||||
name: depName);
|
||||
break;
|
||||
case UniversalBindingMode.asyncStrategy:
|
||||
// Не поддерживается
|
||||
// Not supported
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -97,23 +96,12 @@ class KiwiAdapter extends DIAdapter<KiwiContainer> {
|
||||
|
||||
@override
|
||||
T resolve<T extends Object>({String? named}) {
|
||||
// Для asyncChain нужен resolve<Future<T>>
|
||||
if (T.toString().startsWith('Future<')) {
|
||||
return _container.resolve<T>(named);
|
||||
} else {
|
||||
return _container.resolve<T>(named);
|
||||
}
|
||||
return _container.resolve<T>(named);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<T> resolveAsync<T extends Object>({String? named}) async {
|
||||
if (T.toString().startsWith('Future<')) {
|
||||
// resolve<Future<T>>, unwrap result
|
||||
return Future.value(_container.resolve<T>(named));
|
||||
} else {
|
||||
// Для совместимости с chain/override
|
||||
return Future.value(_container.resolve<T>(named));
|
||||
}
|
||||
Future<T> resolveAsync<T extends Object>({String? named}) {
|
||||
return Future.value(_container.resolve<T>(named));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -123,7 +111,7 @@ class KiwiAdapter extends DIAdapter<KiwiContainer> {
|
||||
|
||||
@override
|
||||
KiwiAdapter openSubScope(String name) {
|
||||
// Возвращаем новый scoped контейнер (отдельный). Наследование не реализовано.
|
||||
// Returns a new scoped container. Inheritance not implemented.
|
||||
return KiwiAdapter(container: KiwiContainer.scoped(), isSubScope: true);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ class YxScopeAdapter extends DIAdapter<UniversalYxScopeContainer> {
|
||||
|
||||
@override
|
||||
void teardown() {
|
||||
// У yx_scope нет явного dispose на ScopeContainer, но можно добавить очистку Map/Deps если потребуется
|
||||
// Ничего не делаем
|
||||
_scope = UniversalYxScopeContainer();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -54,26 +53,13 @@ class YxScopeAdapter extends DIAdapter<UniversalYxScopeContainer> {
|
||||
required UniversalBindingMode bindingMode,
|
||||
}) {
|
||||
if (scenario is UniversalScenario) {
|
||||
if (scenario == UniversalScenario.asyncChain ||
|
||||
bindingMode == UniversalBindingMode.asyncStrategy) {
|
||||
throw UnsupportedError(
|
||||
'YxScope does not support async dependencies or async binding scenarios.');
|
||||
}
|
||||
return (scope) {
|
||||
switch (scenario) {
|
||||
case UniversalScenario.asyncChain:
|
||||
for (int chain = 1; chain <= chainCount; chain++) {
|
||||
for (int level = 1; level <= nestingDepth; level++) {
|
||||
final prevDepName = '${chain}_${level - 1}';
|
||||
final depName = '${chain}_$level';
|
||||
final dep = scope.dep<UniversalService>(
|
||||
() => UniversalServiceImpl(
|
||||
value: depName,
|
||||
dependency: level > 1
|
||||
? scope.depFor<UniversalService>(name: prevDepName).get
|
||||
: null,
|
||||
),
|
||||
name: depName,
|
||||
);
|
||||
scope.register<UniversalService>(dep, name: depName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UniversalScenario.register:
|
||||
final dep = scope.dep<UniversalService>(
|
||||
() => UniversalServiceImpl(value: 'reg', dependency: null),
|
||||
@@ -113,6 +99,8 @@ class YxScopeAdapter extends DIAdapter<UniversalYxScopeContainer> {
|
||||
case UniversalScenario.override:
|
||||
// handled at benchmark level
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (scenario == UniversalScenario.chain ||
|
||||
scenario == UniversalScenario.override) {
|
||||
|
||||
Reference in New Issue
Block a user