feat: add Riverpod adapter, async-chain support via FutureProvider, full DI CLI/bench integration, benchmarking, ascii performance graphs in markdown

This commit is contained in:
Sergey Penkovsky
2025-08-07 13:12:56 +03:00
parent f7a7ea4384
commit 590b876cf4
7 changed files with 173 additions and 8 deletions

View File

@@ -4,9 +4,7 @@ import '../di_adapters/di_adapter.dart';
import '../di_adapters/cherrypick_adapter.dart';
import '../di_adapters/get_it_adapter.dart';
import 'universal_chain_module.dart';
import 'universal_service.dart';
import 'package:get_it/get_it.dart';
import 'package:cherrypick/cherrypick.dart';
import 'package:riverpod/riverpod.dart' as rp;
/// Возвращает универсальную функцию регистрации зависимостей,
/// подходящую под выбранный DI-адаптер.
@@ -41,7 +39,7 @@ void Function(dynamic) getUniversalRegistration(
final prev = level > 1
? await getIt.getAsync<UniversalService>(instanceName: prevDepName)
: null;
return UniversalServiceImpl(value: depName, dependency: prev);
return UniversalServiceImpl(value: depName, dependency: prev as UniversalService?);
},
instanceName: depName,
);
@@ -112,5 +110,62 @@ void Function(dynamic) getUniversalRegistration(
}
};
}
// Riverpod
if (adapter.runtimeType.toString().contains('RiverpodAdapter')) {
// Регистрация Provider-ов по универсальному сценарию
return (providers) {
// providers это Map<String, ProviderBase<Object?>>
switch (scenario) {
case UniversalScenario.register:
providers['UniversalService'] = rp.Provider<UniversalService>((ref) => UniversalServiceImpl(value: 'reg', dependency: null));
break;
case UniversalScenario.named:
providers['impl1'] = rp.Provider<UniversalService>((ref) => UniversalServiceImpl(value: 'impl1'));
providers['impl2'] = rp.Provider<UniversalService>((ref) => UniversalServiceImpl(value: 'impl2'));
break;
case UniversalScenario.chain:
for (int chain = 1; chain <= chainCount; chain++) {
for (int level = 1; level <= nestingDepth; level++) {
final prevDepName = '${chain}_${level - 1}';
final depName = '${chain}_$level';
providers[depName] = rp.Provider<UniversalService>((ref) => UniversalServiceImpl(
value: depName,
dependency: level > 1 ? ref.watch(providers[prevDepName] as rp.ProviderBase<UniversalService>) : null,
));
}
}
// Alias для последнего (универсальное имя)
final depName = '${chainCount}_$nestingDepth';
providers['UniversalService'] = rp.Provider<UniversalService>((ref) => ref.watch(providers[depName] as rp.ProviderBase<UniversalService>));
break;
case UniversalScenario.override:
// handled at benchmark level
break;
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';
providers[depName] = rp.FutureProvider<UniversalService>((ref) async {
return UniversalServiceImpl(
value: depName,
dependency: level > 1
? await ref.watch(providers[prevDepName]!.future) as UniversalService?
: null,
);
});
}
}
// Alias для последнего (универсальное имя)
final depName = '${chainCount}_$nestingDepth';
providers['UniversalService'] = rp.FutureProvider<UniversalService>((ref) async {
return await ref.watch(providers[depName]!.future) as UniversalService;
});
break;
}
};
}
throw UnsupportedError('Unknown DIAdapter type: ${adapter.runtimeType}');
}

View File

@@ -127,14 +127,14 @@ class UniversalChainModule extends Module {
}
}
// Регистрация алиаса без имени (на последний элемент цепочки)
final depName = '${chainCount}_${nestingDepth}';
final depName = '${chainCount}_$nestingDepth';
bind<UniversalService>()
.toProvide(() => currentScope.resolve<UniversalService>(named: depName))
.singleton();
break;
case UniversalScenario.override:
// handled at benchmark level, но алиас нужен прямо в этом scope!
final depName = '${chainCount}_${nestingDepth}';
final depName = '${chainCount}_$nestingDepth';
bind<UniversalService>()
.toProvide(() => currentScope.resolve<UniversalService>(named: depName))
.singleton();