diff --git a/LightweightIocContainer/Interfaces/IIocContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs
index 9a667b8..a3162e3 100644
--- a/LightweightIocContainer/Interfaces/IIocContainer.cs
+++ b/LightweightIocContainer/Interfaces/IIocContainer.cs
@@ -36,7 +36,7 @@ namespace LightweightIocContainer.Interfaces
/// The to register
/// The for this
/// The created
- IRegistrationBase Register(Lifestyle lifestyle = Lifestyle.Transient);
+ ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient);
///
/// Register an Interface with a Type that implements it as a multiton
diff --git a/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs
new file mode 100644
index 0000000..8c68244
--- /dev/null
+++ b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs
@@ -0,0 +1,27 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+
+namespace LightweightIocContainer.Interfaces.Registrations
+{
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the
+ public interface ISingleTypeRegistration : IRegistrationBase
+ {
+ ///
+ /// that is invoked instead of creating an instance of this the default way
+ ///
+ Func FactoryMethod { get; }
+
+ ///
+ /// Pass a that will be invoked instead of creating an instance of this the default way
+ ///
+ /// The
+ /// The current instance of this
+ IRegistrationBase WithFactoryMethod(Func factoryMethod);
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs
index 4c9df25..edd6d88 100644
--- a/LightweightIocContainer/IocContainer.cs
+++ b/LightweightIocContainer/IocContainer.cs
@@ -73,9 +73,9 @@ namespace LightweightIocContainer
/// The to register
/// The for this
/// The created
- public IRegistrationBase Register(Lifestyle lifestyle = Lifestyle.Transient)
+ public ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient)
{
- IRegistrationBase registration = _registrationFactory.Register(lifestyle);
+ ISingleTypeRegistration registration = _registrationFactory.Register(lifestyle);
Register(registration);
return registration;
@@ -213,7 +213,7 @@ namespace LightweightIocContainer
{
resolvedInstance = unitTestCallbackRegistration.UnitTestResolveCallback.Invoke(arguments);
}
- else if (registration is IDefaultRegistration defaultRegistration)
+ else if (registration is IRegistrationBase defaultRegistration)
{
if (defaultRegistration.Lifestyle == Lifestyle.Singleton)
resolvedInstance = GetOrCreateSingletonInstance(defaultRegistration, arguments, resolveStack);
@@ -242,7 +242,7 @@ namespace LightweightIocContainer
/// The arguments to resolve
/// The current resolve stack
/// An existing or newly created singleton instance of the given
- private T GetOrCreateSingletonInstance(IDefaultRegistration registration, object[] arguments, List resolveStack)
+ private T GetOrCreateSingletonInstance(IRegistrationBase registration, object[] arguments, List resolveStack)
{
//if a singleton instance exists return it
object instance = _singletons.FirstOrDefault(s => s.type == typeof(T)).instance;
@@ -306,10 +306,30 @@ namespace LightweightIocContainer
/// The constructor arguments
/// The current resolve stack
/// A newly created instance of the given
- private T CreateInstance(IDefaultRegistration registration, object[] arguments, List resolveStack)
+ private T CreateInstance(IRegistrationBase registration, object[] arguments, List resolveStack)
{
- arguments = ResolveConstructorArguments(registration.ImplementationType, arguments, resolveStack);
- T instance = (T) Activator.CreateInstance(registration.ImplementationType, arguments);
+ T instance;
+ if (registration is IDefaultRegistration defaultRegistration)
+ {
+ arguments = ResolveConstructorArguments(defaultRegistration.ImplementationType, arguments, resolveStack);
+ instance = (T) Activator.CreateInstance(defaultRegistration.ImplementationType, arguments);
+ }
+ else if (registration is ISingleTypeRegistration singleTypeRegistration)
+ {
+ if (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) //type registration without interface -> just create this type
+ {
+ arguments = ResolveConstructorArguments(singleTypeRegistration.InterfaceType, arguments, resolveStack);
+ instance = (T)Activator.CreateInstance(singleTypeRegistration.InterfaceType, arguments);
+ }
+ else //factory method set to create the instance
+ instance = singleTypeRegistration.FactoryMethod(this);
+ }
+ else
+ throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.");
+
registration.OnCreateAction?.Invoke(instance); //TODO: Allow async OnCreateAction?
return instance;
diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml
index abd02ce..613bbb7 100644
--- a/LightweightIocContainer/LightweightIocContainer.xml
+++ b/LightweightIocContainer/LightweightIocContainer.xml
@@ -456,6 +456,24 @@
The
The current instance of this
+
+
+ The to register either only an interface or only a
+
+ The of the
+
+
+
+ that is invoked instead of creating an instance of this the default way
+
+
+
+
+ Pass a that will be invoked instead of creating an instance of this the default way
+
+ The
+ The current instance of this
+
The registration that is used to register an abstract typed factory
@@ -579,7 +597,7 @@
The given is not registered in this
The registration for the given has an unknown
-
+
Gets or creates a singleton instance of a given
@@ -601,7 +619,7 @@
No arguments given
Scope argument not given
-
+
Creates an instance of a given
@@ -759,11 +777,11 @@
- Register a without an interface and create a
+ Register a without an interface and create a
- The to register
- The for this
- A new created with the given parameters
+ The to register
+ The for this
+ A new created with the given parameters
@@ -781,6 +799,31 @@
The abstract typed factory to register
A new created with the given parameters
+
+
+ The to register either only an interface or only a
+
+ The of the
+
+
+
+ The to register either only an interface or only a
+
+ The of the interface or
+ The of the
+
+
+
+ that is invoked instead of creating an instance of this the default way
+
+
+
+
+ Pass a that will be invoked instead of creating an instance of this the default way
+
+ The
+ The current instance of this
+
The registration that is used to register an abstract typed factory
diff --git a/LightweightIocContainer/Registrations/RegistrationFactory.cs b/LightweightIocContainer/Registrations/RegistrationFactory.cs
index e424f8b..8249da8 100644
--- a/LightweightIocContainer/Registrations/RegistrationFactory.cs
+++ b/LightweightIocContainer/Registrations/RegistrationFactory.cs
@@ -35,17 +35,14 @@ namespace LightweightIocContainer.Registrations
}
///
- /// Register a without an interface and create a
+ /// Register a without an interface and create a
///
- /// The to register
- /// The for this
- /// A new created with the given parameters
- public IRegistrationBase Register(Lifestyle lifestyle)
+ /// The to register
+ /// The for this
+ /// A new created with the given parameters
+ public ISingleTypeRegistration Register(Lifestyle lifestyle)
{
- if (typeof(TImplementation).IsInterface)
- throw new InvalidRegistrationException("Can't register an interface without its implementation type.");
-
- return Register(lifestyle);
+ return new SingleTypeRegistration(typeof(T), lifestyle);
}
///
diff --git a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs
new file mode 100644
index 0000000..5a7a793
--- /dev/null
+++ b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs
@@ -0,0 +1,44 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using LightweightIocContainer.Interfaces;
+using LightweightIocContainer.Interfaces.Registrations;
+
+namespace LightweightIocContainer.Registrations
+{
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the
+ public class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration
+ {
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the interface or
+ /// The of the
+ public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle)
+ : base(interfaceType, lifestyle)
+ {
+ Name = $"{InterfaceType.Name}, Lifestyle: {Lifestyle.ToString()}";
+ }
+
+ ///
+ /// that is invoked instead of creating an instance of this the default way
+ ///
+ public Func FactoryMethod { get; private set; }
+
+ ///
+ /// Pass a that will be invoked instead of creating an instance of this the default way
+ ///
+ /// The
+ /// The current instance of this
+ public IRegistrationBase WithFactoryMethod(Func factoryMethod)
+ {
+ FactoryMethod = factoryMethod;
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test.LightweightIocContainer/IocContainerTest.cs b/Test.LightweightIocContainer/IocContainerTest.cs
index 1658ab8..ccffa6c 100644
--- a/Test.LightweightIocContainer/IocContainerTest.cs
+++ b/Test.LightweightIocContainer/IocContainerTest.cs
@@ -166,12 +166,6 @@ namespace Test.LightweightIocContainer
Assert.AreEqual(typeof(ITest), exception.Type);
}
- [Test]
- public void TestRegisterInterfaceWithoutImplementation()
- {
- Assert.Throws(() => _iocContainer.Register());
- }
-
[Test]
public void TestRegisterFactoryWithoutCreate()
{
@@ -217,6 +211,13 @@ namespace Test.LightweightIocContainer
Assert.IsInstanceOf(resolvedTest);
}
+ [Test]
+ public void TestResolveInterfaceWithoutImplementation()
+ {
+ _iocContainer.Register();
+ Assert.Throws(() => _iocContainer.Resolve());
+ }
+
[Test]
public void TestResolveWithParams()
{