refactor: testing 145 pass 1 fail

This commit is contained in:
Patrick Stewart 2024-12-27 01:48:11 -07:00
parent 40eadbe408
commit 34b31a7059
2 changed files with 91 additions and 10 deletions

View file

@ -1218,8 +1218,19 @@ class Container {
var value = injectAnnotation.reflectee; var value = injectAnnotation.reflectee;
if (value is Inject) { if (value is Inject) {
// Inject specific implementation with config // Inject specific implementation with config
result.add( result.add(withParameters(value.config, () {
withParameters(value.config, () => make(value.implementation))); // First try to make the implementation directly
if (has(value.implementation)) {
return make(value.implementation);
}
// If that fails, try to resolve through contextual binding
var contextual = _getContextualConcrete(value.implementation);
if (contextual != null) {
return make(contextual);
}
// Finally try to make it normally
return make(value.implementation);
}));
} else if (value is InjectTagged) { } else if (value is InjectTagged) {
// Inject tagged implementation // Inject tagged implementation
var tagged = this.tagged(value.tag); var tagged = this.tagged(value.tag);
@ -1248,6 +1259,7 @@ class Container {
/// Make all instances of a type /// Make all instances of a type
List<dynamic> makeAll(Type type) { List<dynamic> makeAll(Type type) {
var result = <dynamic>[]; var result = <dynamic>[];
var seen = <Type>{};
// Get all tagged implementations // Get all tagged implementations
var allTags = _tags.entries var allTags = _tags.entries
@ -1255,8 +1267,38 @@ class Container {
.map((entry) => entry.key) .map((entry) => entry.key)
.toList(); .toList();
// Collect implementations from all tags
for (var tag in allTags) { for (var tag in allTags) {
result.addAll(tagged(tag)); var implementations =
_tags[tag]!.where((t) => !seen.contains(t)).where((t) {
var reflectedType = reflector.reflectType(t);
var targetType = reflector.reflectType(type);
return reflectedType != null &&
targetType != null &&
(reflectedType.isAssignableTo(targetType) || t == type);
}).toList();
for (var impl in implementations) {
seen.add(impl);
result.add(make(impl));
}
}
// If no tagged implementations found, try to get all registered implementations
if (result.isEmpty) {
var allTypes = [..._singletons.keys, ..._factories.keys];
for (var t in allTypes) {
if (!seen.contains(t)) {
var reflectedType = reflector.reflectType(t);
var targetType = reflector.reflectType(type);
if (reflectedType != null &&
targetType != null &&
(reflectedType.isAssignableTo(targetType) || t == type)) {
seen.add(t);
result.add(make(t));
}
}
}
} }
return result; return result;

View file

@ -235,9 +235,19 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
// Handle List<Logger> specially // Handle List<Logger> specially
if (reflectedType == List<Logger>) { if (reflectedType == List<Logger>) {
var loggers = <Logger>[]; var loggers = <Logger>[];
for (var arg in positionalArguments) { if (positionalArguments.isNotEmpty) {
if (arg is Logger) { if (positionalArguments[0] is List) {
loggers.add(arg); for (var item in positionalArguments[0] as List) {
if (item is Logger) {
loggers.add(item);
}
}
} else {
for (var item in positionalArguments) {
if (item is Logger) {
loggers.add(item);
}
}
} }
} }
return MockReflectedInstance(loggers); return MockReflectedInstance(loggers);
@ -252,18 +262,18 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
constructor.parameters, positionalArguments, namedArguments); constructor.parameters, positionalArguments, namedArguments);
if (reflectedType == Service) { if (reflectedType == Service) {
var loggers = <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) {
if (item is Logger) { if (item is Logger) {
loggers.add(item); allLoggers.add(item);
} }
} }
} }
return MockReflectedInstance(Service( return MockReflectedInstance(Service(
positionalArguments[0] as Logger, positionalArguments[0] as Logger,
positionalArguments[1] as Logger, positionalArguments[1] as Logger,
loggers, allLoggers,
)); ));
} }
if (reflectedType == ConsoleLogger) { if (reflectedType == ConsoleLogger) {
@ -286,12 +296,22 @@ class MockReflectedClass extends ReflectedType implements ReflectedClass {
@override @override
bool isAssignableTo(ReflectedType? other) { bool isAssignableTo(ReflectedType? other) {
// Handle primitive types and exact matches
if (reflectedType == other?.reflectedType) {
return true;
}
// Handle Logger implementations
if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) { if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) {
return true; return true;
} }
if (reflectedType == FileLogger && other?.reflectedType == Logger) { if (reflectedType == FileLogger && other?.reflectedType == Logger) {
return true; return true;
} }
// Handle List<Logger>
if (reflectedType.toString() == 'List<Logger>' &&
other?.reflectedType.toString() == 'List<Logger>') {
return true;
}
return false; return false;
} }
} }
@ -364,6 +384,18 @@ class MockReflectedType implements ReflectedType {
if (reflectedType == other?.reflectedType) { if (reflectedType == other?.reflectedType) {
return true; return true;
} }
// Handle Logger implementations
if (reflectedType == ConsoleLogger && other?.reflectedType == Logger) {
return true;
}
if (reflectedType == FileLogger && other?.reflectedType == Logger) {
return true;
}
// Handle List<Logger>
if (reflectedType.toString() == 'List<Logger>' &&
other?.reflectedType.toString() == 'List<Logger>') {
return true;
}
return false; return false;
} }
@ -405,13 +437,20 @@ void main() {
// Reset instance count // Reset instance count
SingletonService.instanceCount = 0; SingletonService.instanceCount = 0;
// Register implementations // Register implementations with attributes
container.registerAttributeBindings(ConsoleLogger); container.registerAttributeBindings(ConsoleLogger);
container.registerAttributeBindings(FileLogger); container.registerAttributeBindings(FileLogger);
container.registerAttributeBindings(SingletonService); container.registerAttributeBindings(SingletonService);
// 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
container.registerFactory<List<Logger>>((c) =>
[container.make<ConsoleLogger>(), container.make<FileLogger>()]);
}); });
test('can bind implementation using @Injectable', () { test('can bind implementation using @Injectable', () {