diff --git a/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs index 2159675..8279731 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs @@ -9,5 +9,5 @@ namespace LightweightIocContainer.Interfaces.Registrations; /// public interface IOpenGenericRegistration : ITypedRegistration { - + internal Type CreateGenericImplementationType(); } \ No newline at end of file diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs index f31230a..8a9d370 100644 --- a/LightweightIocContainer/IocContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -235,10 +235,7 @@ public class IocContainer : IIocContainer, IIocResolver switch (result) { case true when registration is IOpenGenericRegistration openGenericRegistration: - { - Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments); - return (true, new InternalToBeResolvedPlaceholder(genericImplementationType, registration, parametersToResolve), null); - } + return (true, new InternalToBeResolvedPlaceholder(openGenericRegistration.CreateGenericImplementationType(), registration, parametersToResolve), null); case true: return (true, new InternalToBeResolvedPlaceholder(registeredType, registration, parametersToResolve), null); } @@ -383,21 +380,16 @@ public class IocContainer : IIocContainer, IIocResolver /// A newly created instance of the given private T CreateInstance(IRegistration registration, object?[]? arguments) { - T instance; - if (registration is IOpenGenericRegistration openGenericRegistration) + T instance = registration switch { - //create generic implementation type from generic arguments of T - Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments); - instance = Creator.CreateInstance(genericImplementationType, arguments); - } - else if (registration is ISingleTypeRegistration singleTypeRegistration) - instance = singleTypeRegistration.FactoryMethod == null ? Creator.CreateInstance(singleTypeRegistration.InterfaceType, arguments) : singleTypeRegistration.FactoryMethod(this); - else if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Multiton } and IMultitonRegistration multitonRegistration) - instance = CreateMultitonInstance(multitonRegistration, arguments); - else if (registration is ITypedRegistration defaultRegistration) - instance = Creator.CreateInstance(defaultRegistration.ImplementationType, arguments); - else - throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}."); + IOpenGenericRegistration openGenericRegistration => Creator.CreateInstance(openGenericRegistration.CreateGenericImplementationType(), arguments), + ISingleTypeRegistration singleTypeRegistration => singleTypeRegistration.FactoryMethod == null + ? Creator.CreateInstance(singleTypeRegistration.InterfaceType, arguments) + : singleTypeRegistration.FactoryMethod(this), + ILifestyleProvider { Lifestyle: Lifestyle.Multiton } and IMultitonRegistration multitonRegistration => CreateMultitonInstance(multitonRegistration, arguments), + ITypedRegistration defaultRegistration => Creator.CreateInstance(defaultRegistration.ImplementationType, arguments), + _ => throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.") + }; if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Singleton }) _singletons.TryAdd(GetType(registration), instance); @@ -741,6 +733,7 @@ public class IocContainer : IIocContainer, IIocResolver private Type GetType(IRegistration registration) => registration switch { + IOpenGenericRegistration openGenericRegistration => openGenericRegistration.CreateGenericImplementationType(), ITypedRegistration typedRegistration => typedRegistration.ImplementationType, ISingleTypeRegistration singleTypeRegistration => singleTypeRegistration.InterfaceType, _ => throw new UnknownRegistrationException($"Unknown registration used: {registration.GetType().Name}.") diff --git a/LightweightIocContainer/Registrations/OpenGenericRegistration.cs b/LightweightIocContainer/Registrations/OpenGenericRegistration.cs index 37c85cb..fb95140 100644 --- a/LightweightIocContainer/Registrations/OpenGenericRegistration.cs +++ b/LightweightIocContainer/Registrations/OpenGenericRegistration.cs @@ -29,6 +29,8 @@ internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistrat /// public Type ImplementationType { get; } + public Type CreateGenericImplementationType() => ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments); + /// /// Validate this /// diff --git a/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs b/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs index 8f09b3e..8b09088 100644 --- a/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs +++ b/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs @@ -20,6 +20,9 @@ public class OpenGenericRegistrationTest [UsedImplicitly] public class Constraint : IConstraint; + + [UsedImplicitly] + public class AnotherConstraint : IConstraint; [UsedImplicitly] [SuppressMessage("ReSharper", "UnusedTypeParameter")] @@ -50,15 +53,27 @@ public class OpenGenericRegistrationTest } [UsedImplicitly] - public interface IA; + public interface IA + { + ITest Test { get; } + } [UsedImplicitly] - public class A : IA + public class A(ITest test) : IA { - public A(ITest test) - { - - } + public ITest Test { get; } = test; + } + + [UsedImplicitly] + public interface IB + { + ITest Test { get; } + } + + [UsedImplicitly] + public class B(ITest test) : IB + { + public ITest Test { get; } = test; } [SetUp] @@ -126,4 +141,20 @@ public class OpenGenericRegistrationTest IA a = _iocContainer.Resolve(); Assert.That(a, Is.TypeOf()); } + + [Test] + public void TestOpenGenericTypeAsParameterDifferentGenericParametersResolveDifferentSingletons() + { + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton)); + + IA a = _iocContainer.Resolve(); + Assert.That(a, Is.TypeOf()); + + IB b = _iocContainer.Resolve(); + Assert.That(b, Is.TypeOf()); + + Assert.That(b.Test, Is.Not.SameAs(a.Test)); + } } \ No newline at end of file