#33: add multipleRegistration handling, rename RegisterMultiton

pull/37/head
Simon Gockner 6 years ago
parent 66b31582c0
commit 024d820f91
  1. 12
      LightweightIocContainer/Interfaces/IIocContainer.cs
  2. 41
      LightweightIocContainer/IocContainer.cs
  3. 12
      Test.LightweightIocContainer/IocContainerTest.cs

@ -29,6 +29,16 @@ namespace LightweightIocContainer.Interfaces
/// <returns>The created <see cref="IRegistration"/></returns> /// <returns>The created <see cref="IRegistration"/></returns>
IDefaultRegistration<TInterface> Register<TInterface, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface; IDefaultRegistration<TInterface> Register<TInterface, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface;
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TImplementation">The <see cref="Type"/> that implements both interfaces</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IRegistrationBase{TInterface}"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2}"/></returns>
IMultipleRegistration<TInterface1, TInterface2> Register<TInterface1, TInterface2, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1;
/// <summary> /// <summary>
/// Register a <see cref="Type"/> without an interface /// Register a <see cref="Type"/> without an interface
/// </summary> /// </summary>
@ -44,7 +54,7 @@ namespace LightweightIocContainer.Interfaces
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam> /// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam> /// <typeparam name="TScope">The Type of the multiton scope</typeparam>
/// <returns>The created <see cref="IRegistration"/></returns> /// <returns>The created <see cref="IRegistration"/></returns>
IMultitonRegistration<TInterface> Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface; IMultitonRegistration<TInterface> RegisterMultiton<TInterface, TImplementation, TScope>() where TImplementation : TInterface;
/// <summary> /// <summary>
/// Register an Interface as an abstract typed factory /// Register an Interface as an abstract typed factory

@ -68,6 +68,26 @@ namespace LightweightIocContainer
return registration; return registration;
} }
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TImplementation">The <see cref="Type"/> that implements both interfaces</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IRegistrationBase{TInterface}"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2> Register<TInterface1, TInterface2, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1
{
IMultipleRegistration<TInterface1, TInterface2> multipleRegistration = _registrationFactory.Register<TInterface1, TInterface2, TImplementation>(lifestyle);
foreach (var registration in multipleRegistration.Registrations)
{
Register(registration);
}
return multipleRegistration;
}
/// <summary> /// <summary>
/// Register a <see cref="Type"/> without an interface /// Register a <see cref="Type"/> without an interface
/// </summary> /// </summary>
@ -89,9 +109,9 @@ namespace LightweightIocContainer
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam> /// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam> /// <typeparam name="TScope">The Type of the multiton scope</typeparam>
/// <returns>The created <see cref="IRegistration"/></returns> /// <returns>The created <see cref="IRegistration"/></returns>
public IMultitonRegistration<TInterface> Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface public IMultitonRegistration<TInterface> RegisterMultiton<TInterface, TImplementation, TScope>() where TImplementation : TInterface
{ {
IMultitonRegistration<TInterface> registration = _registrationFactory.Register<TInterface, TImplementation, TScope>(); IMultitonRegistration<TInterface> registration = _registrationFactory.RegisterMultiton<TInterface, TImplementation, TScope>();
Register(registration); Register(registration);
return registration; return registration;
@ -249,14 +269,22 @@ namespace LightweightIocContainer
/// <returns>An existing or newly created singleton instance of the given <see cref="Type"/></returns> /// <returns>An existing or newly created singleton instance of the given <see cref="Type"/></returns>
private T GetOrCreateSingletonInstance<T>(IRegistrationBase<T> registration, object[] arguments, List<Type> resolveStack) private T GetOrCreateSingletonInstance<T>(IRegistrationBase<T> registration, object[] arguments, List<Type> resolveStack)
{ {
Type type;
if (registration is ITypedRegistrationBase<T> typedRegistration)
type = typedRegistration.ImplementationType;
else if (registration is ISingleTypeRegistration<T> singleTypeRegistration)
type = singleTypeRegistration.InterfaceType;
else
throw new UnknownRegistrationException($"There is no registration {registration.GetType().Name} that can have lifestyle singleton.");
//if a singleton instance exists return it //if a singleton instance exists return it
object instance = _singletons.FirstOrDefault(s => s.type == typeof(T)).instance; object instance = _singletons.FirstOrDefault(s => s.type == type).instance;
if (instance != null) if (instance != null)
return (T) instance; return (T) instance;
//if it doesn't already exist create a new instance and add it to the list //if it doesn't already exist create a new instance and add it to the list
T newInstance = CreateInstance(registration, arguments, resolveStack); T newInstance = CreateInstance(registration, arguments, resolveStack);
_singletons.Add((typeof(T), newInstance)); _singletons.Add((type, newInstance));
return newInstance; return newInstance;
} }
@ -338,7 +366,8 @@ namespace LightweightIocContainer
else else
throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}."); throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.");
registration.OnCreateAction?.Invoke(instance); //TODO: Allow async OnCreateAction? if (registration is IOnCreate<T> onCreateRegistration)
onCreateRegistration.OnCreateAction?.Invoke(instance); //TODO: Allow async OnCreateAction?
return instance; return instance;
} }
@ -403,7 +432,7 @@ namespace LightweightIocContainer
if (!sortedConstructors.Any()) //no public constructor available if (!sortedConstructors.Any()) //no public constructor available
throw new NoPublicConstructorFoundException(type); throw new NoPublicConstructorFoundException(type);
NoMatchingConstructorFoundException noMatchingConstructorFoundException = null; NoMatchingConstructorFoundException noMatchingConstructorFoundException = null; //TestMe: Is this thrown when a matching constructor is found but first a non matching one is found?
foreach (ConstructorInfo ctor in sortedConstructors) foreach (ConstructorInfo ctor in sortedConstructors)
{ {

@ -166,7 +166,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestRegisterMultiton() public void TestRegisterMultiton()
{ {
Assert.DoesNotThrow(() => _iocContainer.Register<ITest, Test, MultitonScope>()); Assert.DoesNotThrow(() => _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>());
} }
[Test] [Test]
@ -271,7 +271,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestResolveMultiton() public void TestResolveMultiton()
{ {
_iocContainer.Register<ITest, Test, MultitonScope>(); _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>();
MultitonScope scope1 = new MultitonScope(); MultitonScope scope1 = new MultitonScope();
MultitonScope scope2 = new MultitonScope(); MultitonScope scope2 = new MultitonScope();
@ -288,7 +288,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestResolveMultitonNoArgs() public void TestResolveMultitonNoArgs()
{ {
_iocContainer.Register<ITest, Test, MultitonScope>(); _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>();
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>()); MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception.Type); Assert.AreEqual(typeof(ITest), exception.Type);
@ -297,7 +297,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestResolveMultitonWrongArgs() public void TestResolveMultitonWrongArgs()
{ {
_iocContainer.Register<ITest, Test, MultitonScope>(); _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>();
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>(new object())); MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>(new object()));
Assert.AreEqual(typeof(ITest), exception.Type); Assert.AreEqual(typeof(ITest), exception.Type);
@ -407,7 +407,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestResolveMultitonFromFactory() public void TestResolveMultitonFromFactory()
{ {
_iocContainer.Register<ITest, Test, MultitonScope>(); _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>();
_iocContainer.RegisterFactory<ITestFactory>(); _iocContainer.RegisterFactory<ITestFactory>();
MultitonScope scope1 = new MultitonScope(); MultitonScope scope1 = new MultitonScope();
@ -427,7 +427,7 @@ namespace Test.LightweightIocContainer
[Test] [Test]
public void TestResolveMultitonFromFactoryClearInstances() public void TestResolveMultitonFromFactoryClearInstances()
{ {
_iocContainer.Register<ITest, Test, MultitonScope>(); _iocContainer.RegisterMultiton<ITest, Test, MultitonScope>();
_iocContainer.RegisterFactory<ITestFactory>(); _iocContainer.RegisterFactory<ITestFactory>();
MultitonScope scope1 = new MultitonScope(); MultitonScope scope1 = new MultitonScope();

Loading…
Cancel
Save