diff --git a/LightweightIocContainer.Validation/IocValidator.cs b/LightweightIocContainer.Validation/IocValidator.cs
index b32f778..df33fc2 100644
--- a/LightweightIocContainer.Validation/IocValidator.cs
+++ b/LightweightIocContainer.Validation/IocValidator.cs
@@ -96,7 +96,7 @@ public class IocValidator
}
catch (Exception)
{
- return null;
+ return new NullParameter(type);
}
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/Factories/FactoryHelper.cs b/LightweightIocContainer/Factories/FactoryHelper.cs
new file mode 100644
index 0000000..d62f1af
--- /dev/null
+++ b/LightweightIocContainer/Factories/FactoryHelper.cs
@@ -0,0 +1,35 @@
+// Author: Gockner, Simon
+// Created: 2022-09-02
+// Copyright(c) 2022 SimonG. All Rights Reserved.
+
+using System.Reflection;
+
+namespace LightweightIocContainer.Factories;
+
+///
+/// Helper class for the
+///
+public class FactoryHelper
+{
+ ///
+ /// Convert `null` passed as argument to to handle it correctly
+ ///
+ /// The create method of the factory
+ /// The arguments passed to the create method
+ /// List of arguments with converted null
+ /// Wrong parameters passed
+ public object?[] ConvertPassedNull(MethodBase createMethod, params object?[] arguments)
+ {
+ if (!arguments.Any())
+ return arguments;
+
+ ParameterInfo[] parameters = createMethod.GetParameters();
+ if (arguments.Length != parameters.Length)
+ throw new Exception("Wrong parameters passed");
+
+ for (int i = 0; i < arguments.Length; i++)
+ arguments[i] ??= new NullParameter(parameters[i].ParameterType);
+
+ return arguments;
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Factories/TypedFactory.cs b/LightweightIocContainer/Factories/TypedFactory.cs
index 060e305..b0c534b 100644
--- a/LightweightIocContainer/Factories/TypedFactory.cs
+++ b/LightweightIocContainer/Factories/TypedFactory.cs
@@ -37,22 +37,28 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
private TFactory CreateFactory(IocContainer container)
{
Type factoryType = typeof(TFactory);
-
+
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory");
TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{factoryType.Name}");
typeBuilder.AddInterfaceImplementation(factoryType);
- //add `private readonly IIocContainer _container` field
+ //add `private readonly IocContainer _container` field
FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IocContainer), FieldAttributes.Private | FieldAttributes.InitOnly);
+
+ //add `private readonly FactoryHelper _helper` field
+ FieldBuilder helperFieldBuilder = typeBuilder.DefineField("_helper", typeof(FactoryHelper), FieldAttributes.Private | FieldAttributes.InitOnly);
//add ctor
- ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IocContainer)});
+ ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IocContainer), typeof(FactoryHelper)});
ILGenerator constructorGenerator = constructorBuilder.GetILGenerator();
constructorGenerator.Emit(OpCodes.Ldarg_0);
constructorGenerator.Emit(OpCodes.Ldarg_1);
constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field
+ constructorGenerator.Emit(OpCodes.Ldarg_0);
+ constructorGenerator.Emit(OpCodes.Ldarg_2);
+ constructorGenerator.Emit(OpCodes.Stfld, helperFieldBuilder); //set `_helper` field
constructorGenerator.Emit(OpCodes.Ret);
foreach (MethodInfo createMethod in CreateMethods)
@@ -60,7 +66,9 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
//create a method that looks like this
//public `createMethod.ReturnType` Create(`createMethod.GetParameters()`)
//{
- // return IIocContainer.Resolve(`createMethod.ReturnType`, params);
+ // createMethod = MethodBase.GetCurrentMethod();
+ // object[] args = _helper.ConvertPassedNull(createMethod, params);
+ // return IocContainer.Resolve(`createMethod.ReturnType`, args);
//}
ParameterInfo[] args = createMethod.GetParameters();
@@ -70,9 +78,16 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
typeBuilder.DefineMethodOverride(methodBuilder, createMethod);
ILGenerator generator = methodBuilder.GetILGenerator();
+ generator.DeclareLocal(typeof(MethodBase));
+ generator.DeclareLocal(typeof(object[]));
+ generator.EmitCall(OpCodes.Call, typeof(MethodBase).GetMethod(nameof(MethodBase.GetCurrentMethod))!, null);
+ generator.Emit(OpCodes.Stloc_0);
+
generator.Emit(OpCodes.Ldarg_0);
- generator.Emit(OpCodes.Ldfld, containerFieldBuilder);
+ generator.Emit(OpCodes.Ldfld, helperFieldBuilder);
+
+ generator.Emit(OpCodes.Ldloc_0);
if (args.Any())
{
@@ -93,8 +108,14 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))!.MakeGenericMethod(typeof(object));
generator.EmitCall(OpCodes.Call, emptyArray, null);
}
+
+ generator.EmitCall(OpCodes.Call, typeof(FactoryHelper).GetMethod(nameof(FactoryHelper.ConvertPassedNull), new[] { typeof(MethodBase), typeof(object?[]) })!, null);
+ generator.Emit(OpCodes.Stloc_1);
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Ldfld, containerFieldBuilder);
+ generator.Emit(OpCodes.Ldloc_1);
- generator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.FactoryResolve), 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);
}
@@ -106,7 +127,7 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
//create a method that looks like this
//public void ClearMultitonInstance()
//{
- // IIocContainer.ClearMultitonInstances();
+ // IocContainer.ClearMultitonInstances();
//}
if (multitonClearMethod.IsGenericMethod)
@@ -134,6 +155,6 @@ public class TypedFactory : TypedFactoryBase, ITypedFactory<
}
}
- return Creator.CreateInstance(typeBuilder.CreateTypeInfo()!.AsType(), container);
+ return Creator.CreateInstance(typeBuilder.CreateTypeInfo()!.AsType(), container, new FactoryHelper());
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs
index 04c1a50..abb5a1a 100644
--- a/LightweightIocContainer/IocContainer.cs
+++ b/LightweightIocContainer/IocContainer.cs
@@ -117,7 +117,7 @@ public class IocContainer : IIocContainer, IIocResolver
/// The given
/// The constructor arguments
/// An instance of the given
- public T FactoryResolve(params object[] arguments) => ResolveInternal(arguments, null, true);
+ public T FactoryResolve(params object?[] arguments) => ResolveInternal(arguments, null, true);
///
/// Gets an instance of a given registered
@@ -127,7 +127,7 @@ public class IocContainer : IIocContainer, IIocResolver
/// 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, bool isFactoryResolve = false) => ResolveInstance(TryResolve(arguments, resolveStack, isFactoryResolve));
+ 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
@@ -484,8 +484,6 @@ public class IocContainer : IIocContainer, IIocResolver
private (bool result, List