diff --git a/packages/service_container/lib/src/container.dart b/packages/service_container/lib/src/container.dart index 30cc4b6..22efcc8 100644 --- a/packages/service_container/lib/src/container.dart +++ b/packages/service_container/lib/src/container.dart @@ -320,36 +320,34 @@ class Container implements ContainerContract, Map { void bindMethod(dynamic method, Function callback) { _methodBindings[_parseBindMethod(method)] = (container, params) { try { - if (params is List) { - return Function.apply(callback, [container, ...params]); - } else if (params != null) { - return callback(container, params); - } else { - return callback(container); - } - } catch (e) { - try { - // Try calling with just the container - return callback(container); - } catch (e) { - try { - // Try calling without any arguments - return callback(); - } catch (e) { - try { - // Try calling with just the params - if (params is List) { - return Function.apply(callback, params); - } else if (params != null) { - return callback(params); - } - } catch (e) { - // If all attempts fail, throw an exception - throw BindingResolutionException( - 'Failed to call bound method: $e'); - } + var callbackMirror = reflect(callback); + var functionMirror = + callbackMirror.type.declarations[Symbol('call')] as MethodMirror; + var parameterCount = functionMirror.parameters.length; + + var args = []; + if (parameterCount > 0) args.add(container); + if (parameterCount > 1) { + if (params is List) { + args.addAll(params); + } else if (params != null) { + args.add(params); } } + + // Ensure we have the correct number of arguments + while (args.length < parameterCount) { + args.add(null); + } + + // Trim excess arguments if we have too many + if (args.length > parameterCount) { + args = args.sublist(0, parameterCount); + } + + return Function.apply(callback, args); + } catch (e) { + throw BindingResolutionException('Failed to call bound method: $e'); } }; } @@ -535,11 +533,30 @@ class Container implements ContainerContract, Map { _resolvingCallbacks.clear(); _afterResolvingCallbacks.clear(); _afterResolvingAttributeCallbacks.clear(); + + // Ensure all resolved flags are reset + for (var key in _resolved.keys.toList()) { + _resolved[key] = false; + } } @override bool resolved(String abstract) { - return _resolved.containsKey(abstract) && _resolved[abstract]!; + abstract = _getAlias(abstract); + return _resolved.containsKey(abstract) || _instances.containsKey(abstract); + } + + bool isAlias(String name) { + return _aliases.containsKey(name); + } + + Map> getBindings() { + return Map.from(_bindings); + } + + bool isShared(String abstract) { + return _bindings[abstract]?['shared'] == true || + _instances.containsKey(abstract); } @override @@ -651,19 +668,6 @@ class Container implements ContainerContract, Map { return _extenders[abstract] ?? []; } - Map> getBindings() { - return Map.from(_bindings); - } - - bool isAlias(String name) { - return _aliases.containsKey(name); - } - - bool isShared(String abstract) { - return _bindings[abstract]?['shared'] == true || - _instances.containsKey(abstract); - } - // Implement Map methods @override diff --git a/packages/service_container/test/container_test.dart b/packages/service_container/test/container_test.dart index 8ed5381..daef2d5 100644 --- a/packages/service_container/test/container_test.dart +++ b/packages/service_container/test/container_test.dart @@ -194,6 +194,59 @@ void main() { var secondInstantiation = container.makeScoped('class'); expect(firstInstantiation, same(secondInstantiation)); }); + test('testForgetInstanceForgetsInstance', () { + var containerConcreteStub = ContainerConcreteStub(); + container.instance('ContainerConcreteStub', containerConcreteStub); + expect(container.isShared('ContainerConcreteStub'), isTrue); + container.forgetInstance('ContainerConcreteStub'); + expect(container.isShared('ContainerConcreteStub'), isFalse); + }); + + test('testForgetInstancesForgetsAllInstances', () { + var stub1 = ContainerConcreteStub(); + var stub2 = ContainerConcreteStub(); + var stub3 = ContainerConcreteStub(); + container.instance('Instance1', stub1); + container.instance('Instance2', stub2); + container.instance('Instance3', stub3); + expect(container.isShared('Instance1'), isTrue); + expect(container.isShared('Instance2'), isTrue); + expect(container.isShared('Instance3'), isTrue); + container.forgetInstances(); + expect(container.isShared('Instance1'), isFalse); + expect(container.isShared('Instance2'), isFalse); + expect(container.isShared('Instance3'), isFalse); + }); + + test('testContainerFlushFlushesAllBindingsAliasesAndResolvedInstances', () { + container.bind('ConcreteStub', (Container c) => ContainerConcreteStub(), + shared: true); + container.alias('ConcreteStub', 'ContainerConcreteStub'); + container.make('ConcreteStub'); + expect(container.resolved('ConcreteStub'), isTrue); + expect(container.isAlias('ContainerConcreteStub'), isTrue); + expect(container.getBindings().containsKey('ConcreteStub'), isTrue); + expect(container.isShared('ConcreteStub'), isTrue); + container.flush(); + expect(container.resolved('ConcreteStub'), isFalse); + expect(container.isAlias('ContainerConcreteStub'), isFalse); + expect(container.getBindings().isEmpty, isTrue); + expect(container.isShared('ConcreteStub'), isFalse); + }); + + test('testResolvedResolvesAliasToBindingNameBeforeChecking', () { + container.bind('ConcreteStub', (Container c) => ContainerConcreteStub(), + shared: true); + container.alias('ConcreteStub', 'foo'); + + expect(container.resolved('ConcreteStub'), isFalse); + expect(container.resolved('foo'), isFalse); + + container.make('ConcreteStub'); + + expect(container.resolved('ConcreteStub'), isTrue); + expect(container.resolved('foo'), isTrue); + }); }); }