From 85262ccca734c4f432d70a98096a24d92a96bd79 Mon Sep 17 00:00:00 2001 From: Patrick Stewart Date: Sun, 29 Dec 2024 21:52:30 -0700 Subject: [PATCH] feature: working on constructor injection 175 pass 2 fail --- .../container/lib/src/container.dart | 60 +++- .../lib/src/contextual_binding_builder.dart | 325 +++++++++++++++++- temp.dart | 0 3 files changed, 367 insertions(+), 18 deletions(-) create mode 100644 temp.dart diff --git a/packages/container/container/lib/src/container.dart b/packages/container/container/lib/src/container.dart index 43333fd..d07cd3b 100644 --- a/packages/container/container/lib/src/container.dart +++ b/packages/container/container/lib/src/container.dart @@ -466,11 +466,21 @@ class Container { '${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 (!has(paramType) && reflector.reflectType(paramType) == null) { + // throw BindingResolutionException( + // 'No binding was found for $paramType required by $t2'); + // } + // } for (var param in constructor.parameters) { + // Skip optional parameters + if (!param.isRequired) continue; + var paramType = param.type.reflectedType; if (!has(paramType) && reflector.reflectType(paramType) == null) { throw BindingResolutionException( - 'No binding was found for $paramType required by $t2'); + 'No binding was found for required parameter $paramType in ${reflectedType.name}'); } } } @@ -491,6 +501,9 @@ class Container { // Add current type to build stack before resolving parameters _buildStack.add(t2); try { + var positional = []; + var named = {}; + for (var param in constructor.parameters) { // Check for parameter override var override = getParameterOverride(param.name); @@ -503,27 +516,42 @@ class Container { continue; } - // No override, resolve normally - var value = make(param.type.reflectedType); - if (param.isNamed) { - named[param.name] = value; + // 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 { - positional.add(value); + // Required parameter, must resolve + var value = make(param.type.reflectedType); + if (param.isNamed) { + named[param.name] = value; + } else { + positional.add(value); + } } } + + var instance = reflectedType.newInstance( + isDefault(constructor.name) ? '' : constructor.name, + positional, + named, []).reflectee; + + instance = _applyExtenders(t2, instance); + _fireResolvingCallbacks(instance); + _fireAfterResolvingCallbacks(instance); + return instance as T; } finally { _buildStack.removeLast(); } - - var instance = reflectedType.newInstance( - isDefault(constructor.name) ? '' : constructor.name, - positional, - named, []).reflectee; - - instance = _applyExtenders(t2, instance); - _fireResolvingCallbacks(instance); - _fireAfterResolvingCallbacks(instance); - return instance as T; } else { throw BindingResolutionException( '$t2 is not a class, and therefore cannot be instantiated.'); diff --git a/packages/container/container/lib/src/contextual_binding_builder.dart b/packages/container/container/lib/src/contextual_binding_builder.dart index 8aeae90..780bd44 100644 --- a/packages/container/container/lib/src/contextual_binding_builder.dart +++ b/packages/container/container/lib/src/contextual_binding_builder.dart @@ -71,9 +71,330 @@ 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 concreteType in concrete) { - container.addContextualBinding(concreteType, abstract, implementation); + for (var abstractType in concrete) { + // Add contextual binding with a factory function + container.addContextualBinding( + abstractType, abstractType, (c) => c.make(implementation)); } } diff --git a/temp.dart b/temp.dart new file mode 100644 index 0000000..e69de29