diff --git a/.idea/.idea.LightweightIocContainer/.idea/modules.xml b/.idea/.idea.LightweightIocContainer/.idea/modules.xml index fd7a90d..0d06f78 100644 --- a/.idea/.idea.LightweightIocContainer/.idea/modules.xml +++ b/.idea/.idea.LightweightIocContainer/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/IIocContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs index d4c1465..efdb7ba 100644 --- a/LightweightIocContainer/Interfaces/IIocContainer.cs +++ b/LightweightIocContainer/Interfaces/IIocContainer.cs @@ -101,6 +101,16 @@ namespace LightweightIocContainer.Interfaces /// The created IMultitonRegistration RegisterMultiton() where TImplementation : TInterface; + /// + /// Register multiple interfaces for a that implements them as a multiton + /// + /// The base interface to register + /// A second interface to register + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2; + /// /// Register an Interface as an abstract typed factory /// diff --git a/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs new file mode 100644 index 0000000..079248d --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs @@ -0,0 +1,17 @@ +// Author: Gockner, Simon +// Created: 2020-11-19 +// Copyright(c) 2020 SimonG. All Rights Reserved. + +namespace LightweightIocContainer.Interfaces.Registrations +{ + /// + /// An to register multiple interfaces for on implementation type that implements them as a multiton + /// + /// The first interface + /// The second interface + /// The implementation + public interface IMultipleMultitonRegistration : IMultitonRegistration, IMultipleRegistration where TImplementation : TInterface1, TInterface2 + { + + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs index 2106215..5b20f0e 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs @@ -17,7 +17,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// /// A base without implementation /// - public interface IMultitonRegistration : IRegistrationBase, IMultitonRegistration + public interface IMultitonRegistration : ITypedRegistrationBase, IMultitonRegistration { /// /// The of the multiton scope diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs index c95a555..0382121 100644 --- a/LightweightIocContainer/IocContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -193,6 +193,22 @@ namespace LightweightIocContainer return registration; } + /// + /// Register multiple interfaces for a that implements them as a multiton + /// + /// The base interface to register + /// A second interface to register + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + public IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2 + { + IMultipleMultitonRegistration registration = _registrationFactory.RegisterMultiton(); + Register(registration); + + return registration; + } + /// /// Register an Interface as an abstract typed factory /// @@ -377,7 +393,7 @@ namespace LightweightIocContainer throw new MultitonResolveException($"Can not resolve multiton without the first argument being the scope (should be of type {registration.Scope}).", typeof(T)); //if a multiton for the given scope exists return it - var instances = _multitons.FirstOrDefault(m => m.type == typeof(T) && m.scope == registration.Scope).instances; //get instances for the given type and scope + var instances = _multitons.FirstOrDefault(m => m.type == registration.ImplementationType && m.scope == registration.Scope).instances; //get instances for the given type and scope (use implementation type to resolve the correct instance for multiple multiton registrations as well) if (instances != null) { if (instances.TryGetValue(scopeArgument, out object instance)) @@ -394,7 +410,7 @@ namespace LightweightIocContainer ConditionalWeakTable weakTable = new ConditionalWeakTable(); weakTable.Add(scopeArgument, newInstance); - _multitons.Add((typeof(T), registration.Scope, weakTable)); + _multitons.Add((registration.ImplementationType, registration.Scope, weakTable)); return newInstance; } @@ -603,7 +619,11 @@ namespace LightweightIocContainer /// The to clear the multiton instances public void ClearMultitonInstances() { - var multitonInstance = _multitons.FirstOrDefault(m => m.type == typeof(T)); + IRegistration registration = FindRegistration(); + if (!(registration is IMultitonRegistration multitonRegistration)) + return; + + var multitonInstance = _multitons.FirstOrDefault(m => m.type == multitonRegistration.ImplementationType); //it is allowed to clear a non existing multiton instance (don't throw an exception) if (multitonInstance == default) diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml index a2891e6..9d9947d 100644 --- a/LightweightIocContainer/LightweightIocContainer.xml +++ b/LightweightIocContainer/LightweightIocContainer.xml @@ -447,6 +447,16 @@ The Type of the multiton scope The created + + + Register multiple interfaces for a that implements them as a multiton + + The base interface to register + A second interface to register + The Type that implements the interface + The Type of the multiton scope + The created + Register an Interface as an abstract typed factory @@ -575,6 +585,14 @@ The Lifestyle of Instances that are created with this + + + An to register multiple interfaces for on implementation type that implements them as a multiton + + The first interface + The second interface + The implementation + The base interface for every to register multiple interfaces @@ -827,6 +845,16 @@ The Type of the multiton scope The created + + + Register multiple interfaces for a that implements them as a multiton + + The base interface to register + A second interface to register + The Type that implements the interface + The Type of the multiton scope + The created + Register an Interface as an abstract typed factory @@ -989,6 +1017,35 @@ The of the implementation The of the + + + An to register multiple interfaces for on implementation type that implements them as a multiton + + The first interface + The second interface + The implementation + + + + An to register multiple interfaces for on implementation type that implements them as a multiton + + The of the first interface + The of the second interface + The of the implementation + The of the multiton scope + + + + A of s that are registered within this + + + + + Pass an that will be invoked when an instance of this type is created + + The + The current instance of this + The base class for every to register multiple interfaces @@ -1299,6 +1356,16 @@ The Type of the multiton scope A new created with the given parameters + + + Register multiple interfaces for a that implements them as a multiton + + The base interface to register + A second interface to register + The Type that implements the interface + The Type of the multiton scope + A new created with the given parameters + Register an Interface as an abstract typed factory and create a diff --git a/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs new file mode 100644 index 0000000..d2ce510 --- /dev/null +++ b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs @@ -0,0 +1,59 @@ +// Author: Gockner, Simon +// Created: 2020-11-19 +// Copyright(c) 2020 SimonG. All Rights Reserved. + +using System; +using System.Collections.Generic; +using LightweightIocContainer.Interfaces.Registrations; + +namespace LightweightIocContainer.Registrations +{ + /// + /// An to register multiple interfaces for on implementation type that implements them as a multiton + /// + /// The first interface + /// The second interface + /// The implementation + public class MultipleMultitonRegistration : MultitonRegistration, IMultipleMultitonRegistration where TImplementation : TInterface1, TInterface2 + { + /// + /// An to register multiple interfaces for on implementation type that implements them as a multiton + /// + /// The of the first interface + /// The of the second interface + /// The of the implementation + /// The of the multiton scope + public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope) + : base(interfaceType1, implementationType, scope) + { + Registrations = new List() + { + new MultitonRegistration(interfaceType1, implementationType, scope), + new MultitonRegistration(interfaceType2, implementationType, scope) + }; + } + + /// + /// A of s that are registered within this + /// + public List Registrations { get; } + + /// + /// Pass an that will be invoked when an instance of this type is created + /// + /// The + /// The current instance of this + public override ITypedRegistrationBase OnCreate(Action action) + { + foreach (var registration in Registrations) + { + if (registration is IMultitonRegistration interface2Registration) + interface2Registration.OnCreate(action); + else if (registration is IMultitonRegistration interface1Registration) + interface1Registration.OnCreate(action); + } + + return this; + } + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/RegistrationFactory.cs b/LightweightIocContainer/Registrations/RegistrationFactory.cs index 7ff2487..03913e5 100644 --- a/LightweightIocContainer/Registrations/RegistrationFactory.cs +++ b/LightweightIocContainer/Registrations/RegistrationFactory.cs @@ -119,6 +119,19 @@ namespace LightweightIocContainer.Registrations return new MultitonRegistration(typeof(TInterface), typeof(TImplementation), typeof(TScope)); } + /// + /// Register multiple interfaces for a that implements them as a multiton + /// + /// The base interface to register + /// A second interface to register + /// The Type that implements the interface + /// The Type of the multiton scope + /// A new created with the given parameters + public IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2 + { + return new MultipleMultitonRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope)); + } + /// /// Register an Interface as an abstract typed factory and create a /// diff --git a/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs b/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs new file mode 100644 index 0000000..59d1188 --- /dev/null +++ b/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs @@ -0,0 +1,102 @@ +// Author: Gockner, Simon +// Created: 2020-11-19 +// Copyright(c) 2020 SimonG. All Rights Reserved. + +using JetBrains.Annotations; +using LightweightIocContainer; +using LightweightIocContainer.Interfaces; +using NUnit.Framework; + +namespace Test.LightweightIocContainer +{ + [TestFixture] + public class MultipleMultitonRegistrationTest + { + private IIocContainer _iocContainer; + + [UsedImplicitly] + public interface ITest : IProvider + { + + } + + public interface IProvider + { + int Number { get; } + void DoSomething(int number); + } + + [UsedImplicitly] + public class Test : ITest + { + public int Number { get; private set; } + + public void DoSomething(int number) => Number = number; + } + + private class MultitonScope + { + + } + + + [SetUp] + public void SetUp() => _iocContainer = new IocContainer(); + + [TearDown] + public void TearDown() => _iocContainer.Dispose(); + + [Test] + public void TestRegisterAndResolveMultipleMultitonRegistration() + { + _iocContainer.RegisterMultiton(); + + MultitonScope scope = new MultitonScope(); + + ITest test = _iocContainer.Resolve(scope); + Assert.NotNull(test); + + IProvider provider = _iocContainer.Resolve(scope); + Assert.NotNull(provider); + Assert.AreEqual(test, provider); + Assert.AreSame(test, provider); + } + + [Test] + public void TestRegisterAndResolveMultipleMultitonRegistrationWithDifferentScope() + { + _iocContainer.RegisterMultiton(); + + MultitonScope scope = new MultitonScope(); + MultitonScope differentScope = new MultitonScope(); + + ITest test = _iocContainer.Resolve(scope); + Assert.NotNull(test); + + IProvider provider = _iocContainer.Resolve(differentScope); + Assert.NotNull(provider); + + Assert.AreNotEqual(test, provider); + Assert.AreNotSame(test, provider); + } + + [Test] + public void TestMultipleMultitonRegistrationOnCreate() + { + _iocContainer.RegisterMultiton().OnCreate(t => t.DoSomething(1)); + + MultitonScope scope = new MultitonScope(); + + ITest test = _iocContainer.Resolve(scope); + Assert.NotNull(test); + Assert.AreEqual(1, test.Number); + + IProvider provider = _iocContainer.Resolve(scope); + Assert.NotNull(provider); + Assert.AreEqual(1, provider.Number); + + Assert.AreEqual(test, provider); + Assert.AreSame(test, provider); + } + } +} \ No newline at end of file