refactor: working on constructor injection 175 pass 2 fail

This commit is contained in:
Patrick Stewart 2024-12-30 01:27:56 -07:00
parent 22ade7f699
commit ab9ebde517
3 changed files with 67 additions and 420 deletions

View file

@ -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 {
// Keep current type on stack for dependency resolution
instance = contextualConcrete(this);
} finally {
_buildStack.add(t2);
}
} 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 = <String, Object>{};
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 = <String, Object>{};
// var positional = [];
// var named = <String, Object>{};
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 = <String, Object>{};
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 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) {
// Skip optional parameter if we can't resolve it
continue;
// Only rethrow for required parameters
if (param.isRequired) {
rethrow;
}
} else {
// Required parameter, must resolve
var value = make(param.type.reflectedType);
if (param.isNamed) {
named[param.name] = value;
} else {
positional.add(value);
// 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<Logger>({'level': 'debug'});
/// ```
T makeWith<T>(Map<String, dynamic> parameters, [Type? type]) {
return withParameters(parameters, () => make<T>(type));
// Push parameters onto stack
_parameterStack.add(parameters);
try {
// Make instance with parameters
return make<T>(type);
} finally {
// Always pop parameters from stack
_parameterStack.removeLast();
}
}
/// Create a factory binding for deferred resolution

View file

@ -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 = <String, Object>{};
// 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);
});
}
}

View file