diff --git a/LightweightIocContainer/Exceptions/DirectResolveWithRegisteredFactoryNotAllowed.cs b/LightweightIocContainer/Exceptions/DirectResolveWithRegisteredFactoryNotAllowed.cs
new file mode 100644
index 0000000..c692655
--- /dev/null
+++ b/LightweightIocContainer/Exceptions/DirectResolveWithRegisteredFactoryNotAllowed.cs
@@ -0,0 +1,26 @@
+// Author: Gockner, Simon
+// Created: 2022-08-31
+// Copyright(c) 2022 SimonG. All Rights Reserved.
+
+using System;
+
+namespace LightweightIocContainer.Exceptions;
+
+///
+/// A direct resolve with a registered factory is not allowed
+///
+public class DirectResolveWithRegisteredFactoryNotAllowed : IocContainerException
+{
+ ///
+ /// A direct resolve with a registered factory is not allowed
+ ///
+ /// The type that can't be resolved directly
+ public DirectResolveWithRegisteredFactoryNotAllowed(Type type)
+ : base($"A direct resolve of type {type} is not allowed! Use the registered factory!") =>
+ Type = type;
+
+ ///
+ /// The that can't be resolved directly
+ ///
+ public Type Type { get; }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Factories/TypedFactory.cs b/LightweightIocContainer/Factories/TypedFactory.cs
index fe7e7f8..ddd0c16 100644
--- a/LightweightIocContainer/Factories/TypedFactory.cs
+++ b/LightweightIocContainer/Factories/TypedFactory.cs
@@ -24,7 +24,7 @@ namespace LightweightIocContainer.Factories
/// The
///
/// The current instance of the
- public TypedFactory(IIocContainer container) => Factory = CreateFactory(container);
+ public TypedFactory(IocContainer container) => Factory = CreateFactory(container);
///
/// The implemented abstract typed factory/>
@@ -36,7 +36,7 @@ namespace LightweightIocContainer.Factories
///
/// Factory registration is invalid
/// Creation of abstract methods are illegal in their current state
- private TFactory CreateFactory(IIocContainer container)
+ private TFactory CreateFactory(IocContainer container)
{
Type factoryType = typeof(TFactory);
@@ -47,10 +47,10 @@ namespace LightweightIocContainer.Factories
typeBuilder.AddInterfaceImplementation(factoryType);
//add `private readonly IIocContainer _container` field
- FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IIocContainer), FieldAttributes.Private | FieldAttributes.InitOnly);
+ FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IocContainer), FieldAttributes.Private | FieldAttributes.InitOnly);
//add ctor
- ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IIocContainer)});
+ ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IocContainer)});
ILGenerator constructorGenerator = constructorBuilder.GetILGenerator();
constructorGenerator.Emit(OpCodes.Ldarg_0);
constructorGenerator.Emit(OpCodes.Ldarg_1);
@@ -96,7 +96,7 @@ namespace LightweightIocContainer.Factories
generator.EmitCall(OpCodes.Call, emptyArray, null);
}
- generator.EmitCall(OpCodes.Callvirt, typeof(IIocResolver).GetMethod(nameof(IIocResolver.Resolve), new[] { typeof(object[]) })!.MakeGenericMethod(createMethod.ReturnType), null);
+ generator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.FactoryResolve), new[] { typeof(object[]) })!.MakeGenericMethod(createMethod.ReturnType), null);
generator.Emit(OpCodes.Castclass, createMethod.ReturnType);
generator.Emit(OpCodes.Ret);
}
@@ -127,7 +127,7 @@ namespace LightweightIocContainer.Factories
multitonClearGenerator.Emit(OpCodes.Ldarg_0);
multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder);
- multitonClearGenerator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.ClearMultitonInstances))!.MakeGenericMethod(typeToClear), null);
+ multitonClearGenerator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.ClearMultitonInstances))!.MakeGenericMethod(typeToClear), null);
multitonClearGenerator.Emit(OpCodes.Ret);
}
else
diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs
index 0fe5c7b..b27627a 100644
--- a/LightweightIocContainer/IocContainer.cs
+++ b/LightweightIocContainer/IocContainer.cs
@@ -113,20 +113,30 @@ namespace LightweightIocContainer
/// An instance of the given
public T Resolve(params object[] arguments) => ResolveInternal(arguments);
+ ///
+ /// Gets an instance of the given for a factory
+ ///
+ /// The given
+ /// The constructor arguments
+ /// An instance of the given
+ public T FactoryResolve(params object[] arguments) => ResolveInternal(arguments, null, true);
+
///
/// Gets an instance of a given registered
///
/// The registered
/// The constructor arguments
/// The current resolve stack
+ /// True if resolve is called from factory, false (default) if not
/// An instance of the given registered
- private T ResolveInternal(object[]? arguments, List? resolveStack = null) => ResolveInstance(TryResolve(arguments, resolveStack));
+ private T ResolveInternal(object[]? arguments, List? resolveStack = null, bool isFactoryResolve = false) => ResolveInstance(TryResolve(arguments, resolveStack, isFactoryResolve));
///
/// Tries to resolve the given with the given arguments
///
/// The given arguments
/// The current resolve stack
+ /// True if resolve is called from factory, false (default) if not
/// The registered
/// An instance of the given registered , an if parameters need to be resolved or an if a factory method is used to create an instance
/// The given is not registered
@@ -134,7 +144,7 @@ namespace LightweightIocContainer
/// Tried resolving a multiton without scope argument
/// No matching constructor for the given found
/// Getting resolve stack failed without exception
- private object TryResolve(object?[]? arguments, List? resolveStack)
+ private object TryResolve(object?[]? arguments, List? resolveStack, bool isFactoryResolve = false)
{
IRegistration registration = FindRegistration() ?? throw new TypeNotRegisteredException(typeof(T));
@@ -145,12 +155,13 @@ namespace LightweightIocContainer
if (existingInstance != null)
return existingInstance;
- if (registration is ISingleTypeRegistration singleTypeRegistration)
+ switch (registration)
{
- if (singleTypeRegistration.InterfaceType.IsInterface && singleTypeRegistration.FactoryMethod == null)
+ case IWithFactoryInternal { Factory: { } } when !isFactoryResolve:
+ throw new DirectResolveWithRegisteredFactoryNotAllowed(typeof(T));
+ case ISingleTypeRegistration singleTypeRegistration when singleTypeRegistration.InterfaceType.IsInterface && singleTypeRegistration.FactoryMethod == null:
throw new InvalidRegistrationException($"Can't register an interface without its implementation type or without a factory method (Type: {singleTypeRegistration.InterfaceType}).");
-
- if (singleTypeRegistration.FactoryMethod != null)
+ case ISingleTypeRegistration { FactoryMethod: { } } singleTypeRegistration:
return new InternalFactoryMethodPlaceholder(singleTypeRegistration);
}
@@ -187,14 +198,15 @@ namespace LightweightIocContainer
/// The registered
/// The given arguments
/// The current resolve stack
+ ///
/// An instance of the given registered , an if parameters need to be resolved or an if a factory method is used to create an instance
/// The given is not registered
/// An interface was registered without an implementation or factory method
/// Tried resolving a multiton without scope argument
/// No matching constructor for the given found
/// Getting resolve stack failed without exception
- internal object? TryResolveNonGeneric(Type type, object?[]? arguments, List? resolveStack) =>
- GenericMethodCaller.CallPrivate(this, nameof(TryResolve), type, arguments, resolveStack);
+ internal object? TryResolveNonGeneric(Type type, object?[]? arguments, List? resolveStack, bool isFactoryResolve = false) =>
+ GenericMethodCaller.CallPrivate(this, nameof(TryResolve), type, arguments, resolveStack, isFactoryResolve);
///
/// Recursively resolve a with the given parameters for an
diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml
index 3776897..cde8b71 100644
--- a/LightweightIocContainer/LightweightIocContainer.xml
+++ b/LightweightIocContainer/LightweightIocContainer.xml
@@ -130,6 +130,22 @@
The constructor that does not match
+
+
+ A direct resolve with a registered factory is not allowed
+
+
+
+
+ A direct resolve with a registered factory is not allowed
+
+ The type that can't be resolved directly
+
+
+
+ The that can't be resolved directly
+
+
Could not find generic method
@@ -341,7 +357,7 @@
The type of the abstract factory
-
+
The
@@ -352,7 +368,7 @@
The implemented abstract typed factory/>
-
+
Creates the factory from the given abstract factory type
@@ -935,21 +951,31 @@
The constructor arguments
An instance of the given
-
+
+
+ Gets an instance of the given for a factory
+
+ The given
+ The constructor arguments
+ An instance of the given
+
+
Gets an instance of a given registered
The registered
The constructor arguments
The current resolve stack
+ True if resolve is called from factory, false (default) if not
An instance of the given registered
-
+
Tries to resolve the given with the given arguments
The given arguments
The current resolve stack
+ True if resolve is called from factory, false (default) if not
The registered
An instance of the given registered , an if parameters need to be resolved or an if a factory method is used to create an instance
The given is not registered
@@ -958,13 +984,14 @@
No matching constructor for the given found
Getting resolve stack failed without exception
-
+
Tries to resolve the given with the given arguments without generic arguments
The registered
The given arguments
The current resolve stack
+
An instance of the given registered , an if parameters need to be resolved or an if a factory method is used to create an instance
The given is not registered
An interface was registered without an implementation or factory method
diff --git a/LightweightIocContainer/Validation/IocValidator.cs b/LightweightIocContainer/Validation/IocValidator.cs
index 231e801..e2a45c6 100644
--- a/LightweightIocContainer/Validation/IocValidator.cs
+++ b/LightweightIocContainer/Validation/IocValidator.cs
@@ -58,7 +58,7 @@ namespace LightweightIocContainer.Validation
.FirstOrDefault(p => parameterType.IsInstanceOfType(p.parameter))
select definedParameter == default ? GetMockOrDefault(parameterType) : definedParameter.parameter).ToArray())
.ToList()
- .ForEach(p => TryResolve(registration.InterfaceType, p, validationExceptions));
+ .ForEach(p => TryResolve(registration.InterfaceType, p, validationExceptions, true));
}
else
TryResolve(registration.InterfaceType, null, validationExceptions);
@@ -68,11 +68,11 @@ namespace LightweightIocContainer.Validation
throw new AggregateException("Validation failed.", validationExceptions);
}
- private void TryResolve(Type type, object?[]? arguments, List validationExceptions)
+ private void TryResolve(Type type, object?[]? arguments, List validationExceptions, bool isFactoryResolve = false)
{
try
{
- _iocContainer.TryResolveNonGeneric(type, arguments, null);
+ _iocContainer.TryResolveNonGeneric(type, arguments, null, isFactoryResolve);
}
catch (Exception exception)
{
diff --git a/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs
index b437f41..851388d 100644
--- a/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs
+++ b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs
@@ -112,7 +112,7 @@ namespace Test.LightweightIocContainer
_iocContainer.Register(r => r.Add().WithFactory());
ITestFactory factory = _iocContainer.Resolve();
- ITest test = _iocContainer.Resolve();
+ ITest test = factory.Create();
Assert.IsInstanceOf(factory);
Assert.IsInstanceOf(test);
@@ -124,7 +124,7 @@ namespace Test.LightweightIocContainer
_iocContainer.Register(r => r.Add().WithFactory());
ITestFactory factory = _iocContainer.Resolve();
- ITest test = _iocContainer.Resolve();
+ ITest test = factory.Create();
Assert.IsInstanceOf(factory);
Assert.IsInstanceOf(test);
diff --git a/Test.LightweightIocContainer/MultiLayerResolveTest.cs b/Test.LightweightIocContainer/MultiLayerResolveTest.cs
index 1e7181c..16505c3 100644
--- a/Test.LightweightIocContainer/MultiLayerResolveTest.cs
+++ b/Test.LightweightIocContainer/MultiLayerResolveTest.cs
@@ -30,6 +30,7 @@ public class MultiLayerResolveTest
[UsedImplicitly]
public interface IBFactory
{
+ IB Create();
IB Create(C c);
}
@@ -76,7 +77,8 @@ public class MultiLayerResolveTest
container.Register(r => r.Add().WithFactory());
container.Register(r => r.Add().WithFactory());
- IA a = container.Resolve();
+ IAFactory aFactory = container.Resolve();
+ IA a = aFactory.Create();
Assert.IsInstanceOf(a);
}
@@ -88,7 +90,8 @@ public class MultiLayerResolveTest
container.Register(r => r.Add().WithFactory());
container.Register(r => r.Add().WithFactoryMethod(_ => new C("test")));
- IB b = container.Resolve();
+ IBFactory bFactory = container.Resolve();
+ IB b = bFactory.Create();
Assert.IsInstanceOf(b);
}