diff --git a/packages/container/container/lib/src/container.dart b/packages/container/container/lib/src/container.dart index d07cd3b..f4e491b 100644 --- a/packages/container/container/lib/src/container.dart +++ b/packages/container/container/lib/src/container.dart @@ -299,90 +299,20 @@ class Container { if (contextualConcrete != null) { dynamic instance; if (contextualConcrete is Function) { - // Remove current type from stack to avoid circular dependency - _buildStack.removeLast(); - try { - instance = contextualConcrete(this); - } finally { - _buildStack.add(t2); - } + // Keep current type on stack for dependency resolution + instance = contextualConcrete(this); } else if (contextualConcrete is Type) { // For Type bindings, we need to use reflection to create the instance - _buildStack.removeLast(); // Remove current type from stack - try { - var reflectedType = reflector.reflectType(contextualConcrete); - if (reflectedType is ReflectedClass) { - bool isDefault(String name) { - return name.isEmpty || name == reflectedType.name; - } - - var constructor = reflectedType.constructors.firstWhere( - (c) => isDefault(c.name), - orElse: (() => throw BindingResolutionException( - '${reflectedType.name} has no default constructor, and therefore cannot be instantiated.'))); - - var positional = []; - var named = {}; - - for (var param in constructor.parameters) { - // Check for parameter override - var override = getParameterOverride(param.name); - if (override != null) { - if (param.isNamed) { - named[param.name] = override; - } else { - positional.add(override); - } - continue; - } - - // No override, resolve normally - var value = make(param.type.reflectedType); - if (param.isNamed) { - named[param.name] = value; - } else { - positional.add(value); - } - } - - try { - dynamic tempInstance; - try { - tempInstance = reflectedType.newInstance( - isDefault(constructor.name) ? '' : constructor.name, - positional, - named, []).reflectee; - } on AbstractClassInstantiationError { - throw BindingResolutionException( - 'Cannot instantiate abstract class ${reflectedType.name}'); - } - - tempInstance = _applyExtenders(t2, tempInstance); - _fireResolvingCallbacks(tempInstance); - _fireAfterResolvingCallbacks(tempInstance); - return tempInstance as T; - } catch (e) { - if (e is AbstractClassInstantiationError) { - throw BindingResolutionException( - 'Cannot instantiate abstract class ${reflectedType.name}'); - } - rethrow; - } - } - } finally { - _buildStack.add(t2); // Add it back - } + instance = make(contextualConcrete); } if (instance != null) { instance = _applyExtenders(t2, instance); - var typedInstance = instance as T; - _fireResolvingCallbacks(typedInstance); - _fireAfterResolvingCallbacks(typedInstance); - return typedInstance; + _fireResolvingCallbacks(instance); + _fireAfterResolvingCallbacks(instance); + return instance as T; } } - // Check for contextual binding in parent classes var parentContextual = _getContextualConcreteFromParent(t2); if (parentContextual != null) { @@ -485,8 +415,8 @@ class Container { } } - var positional = []; - var named = {}; + // var positional = []; + // var named = {}; if (reflectedType is ReflectedClass) { bool isDefault(String name) { @@ -498,6 +428,17 @@ class Container { orElse: (() => throw BindingResolutionException( '${reflectedType.name} has no default constructor, and therefore cannot be instantiated.'))); + // Check if we can resolve all constructor parameters + for (var param in constructor.parameters) { + var paramType = param.type.reflectedType; + if (param.isRequired && + !has(paramType) && + reflector.reflectType(paramType) == null) { + throw BindingResolutionException( + 'No binding was found for required parameter $paramType in ${reflectedType.name}'); + } + } + // Add current type to build stack before resolving parameters _buildStack.add(t2); try { @@ -505,7 +446,7 @@ class Container { var named = {}; for (var param in constructor.parameters) { - // Check for parameter override + // Check for parameter override first var override = getParameterOverride(param.name); if (override != null) { if (param.isNamed) { @@ -516,27 +457,26 @@ class Container { continue; } - // Skip optional parameters if we can't resolve them - if (!param.isRequired) { - try { - var value = make(param.type.reflectedType); - if (param.isNamed) { - named[param.name] = value; - } else { - positional.add(value); - } - } catch (e) { - // Skip optional parameter if we can't resolve it - continue; - } - } else { - // Required parameter, must resolve + // Try to resolve the parameter + try { var value = make(param.type.reflectedType); if (param.isNamed) { + // For named parameters, only add if we successfully resolved named[param.name] = value; } else { + // For positional parameters, handle errors positional.add(value); } + } catch (e) { + // Only rethrow for required parameters + if (param.isRequired) { + rethrow; + } + // For optional positional parameters, add null + if (!param.isNamed) { + positional.add(null); + } + // Skip optional named parameters that can't be resolved } } @@ -1267,7 +1207,15 @@ class Container { /// var logger = container.makeWith({'level': 'debug'}); /// ``` T makeWith(Map parameters, [Type? type]) { - return withParameters(parameters, () => make(type)); + // Push parameters onto stack + _parameterStack.add(parameters); + try { + // Make instance with parameters + return make(type); + } finally { + // Always pop parameters from stack + _parameterStack.removeLast(); + } } /// Create a factory binding for deferred resolution diff --git a/packages/container/container/lib/src/contextual_binding_builder.dart b/packages/container/container/lib/src/contextual_binding_builder.dart index 780bd44..2bbf19a 100644 --- a/packages/container/container/lib/src/contextual_binding_builder.dart +++ b/packages/container/container/lib/src/contextual_binding_builder.dart @@ -33,9 +33,17 @@ class ContextualBindingBuilder { /// Bind directly to a concrete implementation void to(Type implementation) { - for (var concreteType in concrete) { - container.addContextualBinding( - concreteType, concreteType, implementation); + for (var abstractType in concrete) { + // Add contextual binding with a factory function + container.addContextualBinding(abstractType, abstractType, (c) { + // Get parameter overrides + var overrides = c.getParameterOverride('name'); + if (overrides != null) { + return c.withParameters( + {'name': overrides}, () => c.make(implementation)); + } + return c.make(implementation); + }); } } } @@ -70,331 +78,22 @@ class ContextualImplementationBuilder { } } - /// Bind to a concrete implementation type - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Add contextual binding with implementation as the value - // container.addContextualBinding( - // concreteType, concreteType, implementation); - // // Also add a contextual binding with implementation as the key - // container.addContextualBinding( - // implementation, concreteType, implementation); - // // Also register a singleton for direct resolution - // container.registerSingleton(container.make(implementation), - // as: concreteType); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Register a factory that creates the implementation - // container.registerFactory( - // (c) => c.withParameters({}, () { - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }), - // as: concreteType); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Keep existing contextual binding - // container.addContextualBinding( - // concreteType, concreteType, implementation); - - // // Add factory that returns implementation instance - // container.registerFactory((c) { - // // Create implementation instance - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // // Get all parameter overrides - // var positional = []; - // var named = {}; - // for (var param in constructor.parameters) { - // var override = c.getParameterOverride(param.name); - // if (override != null) { - // if (param.isNamed) { - // named[param.name] = override; - // } else { - // positional.add(override); - // } - // } - // } - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // positional, - // named, []).reflectee; - // } - - // return c.make(implementation); - // }, as: concreteType); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Register a factory that returns implementation instance - // container.registerFactory((c) { - // // Get parameter overrides - // var overrides = c.getParameterOverride('name'); - // if (overrides != null) { - // return c.withParameters({'name': overrides}, () { - // // Create a new instance of the implementation - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {'name': overrides}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }); - // } - - // // Create a new instance of the implementation - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }, as: concreteType); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Add contextual binding with a factory function - // container.addContextualBinding( - // concreteType, concreteType, (c) => c.make(implementation)); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Add contextual binding with a factory function that handles both cases - // container.addContextualBinding(concreteType, concreteType, (c) { - // try { - // return c.make(implementation); - // } catch (e) { - // if (e.toString().contains('Cannot instantiate abstract class')) { - // return null; - // } - // rethrow; - // } - // }); - // } - // } - - // void to(Type implementation) { - // for (var concreteType in concrete) { - // // Add contextual binding with a factory function - // container.addContextualBinding(implementation, concreteType, (c) { - // // Get parameter overrides first - // var overrides = c.getParameterOverride('name'); - // if (overrides != null) { - // return c.withParameters({'name': overrides}, () { - // return c.make(implementation); - // }); - // } - // return c.make(implementation); - // }); - // } - // } - - // void to(Type implementation) { - // for (var abstractType in concrete) { - // // Register a factory that returns implementation instance - // container.registerFactory((c) { - // // Get parameter overrides first - // var overrides = c.getParameterOverride('name'); - // if (overrides != null) { - // return c.withParameters({'name': overrides}, () { - // // Create a new instance of the implementation - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {'name': overrides}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }); - // } - - // // Create a new instance of the implementation - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }, as: abstractType); - // } - // } - - // void to(Type implementation) { - // for (var abstractType in concrete) { - // // Add contextual binding from abstract to implementation - // container.addContextualBinding( - // abstractType, abstractType, implementation); - - // // Register a factory that handles parameter overrides - // container.registerFactory((c) { - // // Get parameter overrides - // var nameOverride = c.getParameterOverride('name'); - // if (nameOverride != null) { - // return c.withParameters( - // {'name': nameOverride}, () => c.make(implementation)); - // } - // return c.make(implementation); - // }, as: abstractType); - // } - // } - - // void to(Type implementation) { - // for (var abstractType in concrete) { - // // Add contextual binding with a factory function - // container.addContextualBinding(abstractType, abstractType, (c) { - // // Get parameter overrides first - // var nameOverride = c.getParameterOverride('name'); - // if (nameOverride != null) { - // return c.withParameters({'name': nameOverride}, () { - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {'name': nameOverride}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }); - // } - - // // Create implementation instance - // var reflectedType = c.reflector.reflectType(implementation); - // if (reflectedType is ReflectedClass) { - // bool isDefault(String name) { - // return name.isEmpty || name == reflectedType.name; - // } - - // var constructor = reflectedType.constructors.firstWhere( - // (c) => isDefault(c.name), - // orElse: (() => throw BindingResolutionException( - // '${reflectedType.name} has no default constructor'))); - - // return reflectedType.newInstance( - // isDefault(constructor.name) ? '' : constructor.name, - // [], - // {}, - // []).reflectee; - // } - // throw BindingResolutionException( - // '$implementation is not a class, and therefore cannot be instantiated.'); - // }); - // } - // } - - // void to(Type implementation) { - // for (var abstractType in concrete) { - // // Register a factory that handles parameter overrides - // container.registerFactory((c) => c.make(implementation), - // as: abstractType); - // } - // } - void to(Type implementation) { for (var abstractType in concrete) { // Add contextual binding with a factory function - container.addContextualBinding( - abstractType, abstractType, (c) => c.make(implementation)); + container.addContextualBinding(abstractType, abstractType, (c) { + // Get parameter overrides + var overrides = c.getParameterOverride('name'); + if (overrides != null) { + // Create instance with named parameters + var reflectedType = c.reflector.reflectType(implementation); + if (reflectedType is ReflectedClass) { + return reflectedType + .newInstance('', [], {'name': overrides}, []).reflectee; + } + } + return c.make(implementation); + }); } } diff --git a/temp.dart b/temp.dart deleted file mode 100644 index e69de29..0000000