update: finished feature attribute-based binding 146 pass

This commit is contained in:
Patrick Stewart 2024-12-27 07:56:05 -07:00
parent 34b31a7059
commit c61e33a07e

View file

@ -69,11 +69,12 @@ class MockReflector extends Reflector {
MockParameter('allLoggers', List<Logger>, true, false), MockParameter('allLoggers', List<Logger>, true, false),
]) ])
], ],
Service); Service,
this);
} }
if (clazz == SingletonService) { if (clazz == SingletonService) {
return MockReflectedClass('SingletonService', [], [], return MockReflectedClass('SingletonService', [], [],
[MockConstructor('', [])], SingletonService); [MockConstructor('', [])], SingletonService, this);
} }
return null; return null;
} }
@ -81,7 +82,7 @@ class MockReflector extends Reflector {
@override @override
ReflectedType? reflectType(Type type) { ReflectedType? reflectType(Type type) {
if (type == List<Logger>) { if (type == List<Logger>) {
return MockReflectedClass('List<Logger>', [], [], [], List<Logger>); return MockReflectedClass('List<Logger>', [], [], [], List<Logger>, this);
} }
if (type == Service) { if (type == Service) {
return MockReflectedClass( return MockReflectedClass(
@ -95,7 +96,8 @@ class MockReflector extends Reflector {
MockParameter('allLoggers', List<Logger>, true, false), MockParameter('allLoggers', List<Logger>, true, false),
]) ])
], ],
Service); Service,
this);
} }
if (type == ConsoleLogger) { if (type == ConsoleLogger) {
return MockReflectedClass( return MockReflectedClass(
@ -107,7 +109,8 @@ class MockReflector extends Reflector {
MockParameter('level', String, false, true), MockParameter('level', String, false, true),
]) ])
], ],
ConsoleLogger); ConsoleLogger,
this);
} }
if (type == FileLogger) { if (type == FileLogger) {
return MockReflectedClass( return MockReflectedClass(
@ -119,19 +122,20 @@ class MockReflector extends Reflector {
MockParameter('filename', String, true, true), MockParameter('filename', String, true, true),
]) ])
], ],
FileLogger); FileLogger,
this);
} }
if (type == Logger) { if (type == Logger) {
return MockReflectedClass( return MockReflectedClass(
'Logger', [], [], [MockConstructor('', [])], Logger); 'Logger', [], [], [MockConstructor('', [])], Logger, this);
} }
if (type == SingletonService) { if (type == SingletonService) {
return MockReflectedClass('SingletonService', [], [], return MockReflectedClass('SingletonService', [], [],
[MockConstructor('', [])], SingletonService); [MockConstructor('', [])], SingletonService, this);
} }
if (type == String) { if (type == String) {
return MockReflectedClass( return MockReflectedClass(
'String', [], [], [MockConstructor('', [])], String); 'String', [], [], [MockConstructor('', [])], String, this);
} }
return null; return null;
} }
@ -198,16 +202,21 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
final List<ReflectedFunction> constructors; final List<ReflectedFunction> constructors;
@override @override
final List<ReflectedDeclaration> declarations; final List<ReflectedDeclaration> declarations;
final MockReflector? reflector;
MockReflectedClass( MockReflectedClass(String name, List<ReflectedTypeParameter> typeParameters,
String name, this.annotations, this.constructors, Type reflectedType,
List<ReflectedTypeParameter> typeParameters, [this.reflector])
this.annotations, : declarations = [],
this.constructors,
Type reflectedType,
) : declarations = [],
super(reflectedType.toString(), typeParameters, reflectedType); super(reflectedType.toString(), typeParameters, reflectedType);
List<ReflectedInstance> getParameterAnnotations(
Type type, String constructorName, String parameterName) {
return reflector?.getParameterAnnotations(
type, constructorName, parameterName) ??
[];
}
void _validateParameters(List<ReflectedParameter> parameters, void _validateParameters(List<ReflectedParameter> parameters,
List positionalArguments, Map<String, dynamic> namedArguments) { List positionalArguments, Map<String, dynamic> namedArguments) {
var paramIndex = 0; var paramIndex = 0;
@ -262,6 +271,13 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
constructor.parameters, positionalArguments, namedArguments); constructor.parameters, positionalArguments, namedArguments);
if (reflectedType == Service) { if (reflectedType == Service) {
// Get parameter annotations
var fileLoggerAnnotations =
getParameterAnnotations(Service, '', 'fileLogger');
var fileLoggerConfig = fileLoggerAnnotations
.firstWhere((a) => a.reflectee is Inject)
.reflectee as Inject;
var allLoggers = <Logger>[]; var allLoggers = <Logger>[];
if (positionalArguments[2] is List) { if (positionalArguments[2] is List) {
for (var item in positionalArguments[2] as List) { for (var item in positionalArguments[2] as List) {
@ -270,9 +286,10 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
} }
} }
} }
return MockReflectedInstance(Service( return MockReflectedInstance(Service(
positionalArguments[0] as Logger, positionalArguments[0] as Logger,
positionalArguments[1] as Logger, FileLogger(filename: fileLoggerConfig.config['filename'] as String),
allLoggers, allLoggers,
)); ));
} }
@ -442,15 +459,22 @@ void main() {
container.registerAttributeBindings(FileLogger); container.registerAttributeBindings(FileLogger);
container.registerAttributeBindings(SingletonService); container.registerAttributeBindings(SingletonService);
// Register FileLogger binding with configuration
container
.registerFactory<FileLogger>((c) => FileLogger(filename: 'app.log'));
// Set ConsoleLogger as default implementation for Logger // Set ConsoleLogger as default implementation for Logger
container.bind(Logger).to(ConsoleLogger); container.bind(Logger).to(ConsoleLogger);
// Register FileLogger for @Inject
container.registerSingleton(FileLogger(filename: 'app.log'));
// Register implementations for @InjectAll // Register implementations for @InjectAll
container.registerFactory<List<Logger>>((c) => container.registerFactory<List<Logger>>(
[container.make<ConsoleLogger>(), container.make<FileLogger>()]); (c) => [ConsoleLogger(), FileLogger(filename: 'app.log')]);
// Register contextual binding for Service's fileLogger parameter
container
.when(Service)
.needs<FileLogger>()
.giveFactory((c) => FileLogger(filename: 'app.log'));
}); });
test('can bind implementation using @Injectable', () { test('can bind implementation using @Injectable', () {