import 'package:benchmark_di/scenarios/universal_binding_mode.dart'; import 'package:benchmark_di/scenarios/universal_scenario.dart'; import 'package:benchmark_di/scenarios/universal_service.dart'; import 'package:riverpod/riverpod.dart' as rp; import 'di_adapter.dart'; /// Унифицированный DIAdapter для Riverpod с поддержкой scopes и строгой типизацией. class RiverpodAdapter extends DIAdapter>> { rp.ProviderContainer? _container; final Map> _namedProviders; final rp.ProviderContainer? _parent; RiverpodAdapter({ rp.ProviderContainer? container, Map>? providers, rp.ProviderContainer? parent, bool isSubScope = false, }) : _container = container, _namedProviders = providers ?? >{}, _parent = parent; @override void setupDependencies( void Function(Map> container) registration) { _container ??= _parent == null ? rp.ProviderContainer() : rp.ProviderContainer(parent: _parent); registration(_namedProviders); } @override T resolve({String? named}) { final key = named ?? T.toString(); final provider = _namedProviders[key]; if (provider == null) { throw Exception('Provider not found for $key'); } return _container!.read(provider) as T; } @override Future resolveAsync({String? named}) async { final key = named ?? T.toString(); final provider = _namedProviders[key]; if (provider == null) { throw Exception('Provider not found for $key'); } // Если это FutureProvider — используем .future if (provider.runtimeType.toString().contains('FutureProvider')) { return await _container!.read((provider as dynamic).future) as T; } return resolve(named: named); } @override void teardown() { _container?.dispose(); _container = null; _namedProviders.clear(); } @override RiverpodAdapter openSubScope(String name) { final newContainer = rp.ProviderContainer(parent: _container); return RiverpodAdapter( container: newContainer, providers: Map.of(_namedProviders), parent: _container, isSubScope: true, ); } @override Future waitForAsyncReady() async { // Riverpod синхронный по умолчанию. return; } @override Registration>> universalRegistration({ required S scenario, required int chainCount, required int nestingDepth, required UniversalBindingMode bindingMode, }) { if (scenario is UniversalScenario) { return (providers) { switch (scenario) { case UniversalScenario.register: providers['UniversalService'] = rp.Provider( (ref) => UniversalServiceImpl(value: 'reg', dependency: null)); break; case UniversalScenario.named: providers['impl1'] = rp.Provider( (ref) => UniversalServiceImpl(value: 'impl1')); providers['impl2'] = rp.Provider( (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((ref) => UniversalServiceImpl( value: depName, dependency: level > 1 ? ref.watch(providers[prevDepName] as rp.ProviderBase) : null, )); } } final depName = '${chainCount}_$nestingDepth'; providers['UniversalService'] = rp.Provider( (ref) => ref.watch( providers[depName] as rp.ProviderBase)); 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((ref) async { return UniversalServiceImpl( value: depName, dependency: level > 1 ? await ref.watch((providers[prevDepName] as rp.FutureProvider) .future) as UniversalService? : null, ); }); } } final depName = '${chainCount}_$nestingDepth'; providers['UniversalService'] = rp.FutureProvider((ref) async { return await ref.watch( (providers[depName] as rp.FutureProvider) .future); }); break; } }; } throw UnsupportedError( 'Scenario $scenario not supported by RiverpodAdapter'); } }