#22: Simplify registration:

- call register methods directly from container
- make RegistrationFactory internal
pull/32/head
Simon Gockner 6 years ago
parent 2d4aa06c2c
commit 14311a69a3
  1. 59
      LightweightIocContainer/Interfaces/IIocContainer.cs
  2. 97
      LightweightIocContainer/IocContainer.cs
  3. 128
      LightweightIocContainer/LightweightIocContainer.xml
  4. 35
      LightweightIocContainer/Registrations/RegistrationFactory.cs
  5. 4
      Test.LightweightIocContainer/AssemblyInstallerTest.cs
  6. 6
      Test.LightweightIocContainer/DefaultRegistrationTest.cs
  7. 81
      Test.LightweightIocContainer/IocContainerTest.cs
  8. 2
      Test.LightweightIocContainer/Test.LightweightIocContainer.csproj

@ -22,11 +22,62 @@ namespace LightweightIocContainer.Interfaces
IIocContainer Install(params IIocInstaller[] installers);
/// <summary>
/// Add the <see cref="IRegistrationBase"/> to the the <see cref="IIocContainer"/>
/// Register an Interface with a Type that implements it/>
/// </summary>
/// <param name="registration">The given <see cref="IRegistrationBase"/></param>
/// <exception cref="MultipleRegistrationException">The <see cref="Type"/> is already registered in this <see cref="IIocContainer"/></exception>
void Register(IRegistrationBase registration);
/// <typeparam name="TInterface">The Interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
void Register<TInterface, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface;
/// <summary>
/// Register a <see cref="Type"/> without an interface/>
/// </summary>
/// <typeparam name="TImplementation">The <see cref="Type"/> to register</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
void Register<TImplementation>(Lifestyle lifestyle = Lifestyle.Transient);
/// <summary>
/// Register an Interface with a Type that implements it as a multiton/>
/// </summary>
/// <typeparam name="TInterface">The Interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam>
void Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface;
/// <summary>
/// Register an Interface with a Type that implements it/>
/// </summary>
/// <param name="tInterface">The Interface to register</param>
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
void Register(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient);
/// <summary>
/// Register a <see cref="Type"/> without an interface/>
/// </summary>
/// <param name="tImplementation">The <see cref="Type"/> to register</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
void Register(Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient);
/// <summary>
/// Register an Interface with a Type that implements it as a multiton/>
/// </summary>
/// <param name="tInterface">The Interface to register</param>
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="tScope">The Type of the multiton scope</param>
void Register(Type tInterface, Type tImplementation, Type tScope);
/// <summary>
/// Register an Interface as an abstract typed factory/>
/// </summary>
/// <typeparam name="TFactory">The abstract typed factory to register</typeparam>
void RegisterFactory<TFactory>();
/// <summary>
/// Register an Interface as an abstract typed factory/>
/// </summary>
/// <param name="tFactory">The abstract typed factory to register</param>
void RegisterFactory(Type tFactory);
/// <summary>
/// Gets an instance of the given <see cref="Type"/>

@ -12,6 +12,7 @@ using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
using LightweightIocContainer.Registrations;
namespace LightweightIocContainer
{
@ -20,10 +21,22 @@ namespace LightweightIocContainer
/// </summary>
public class IocContainer : IIocContainer
{
private readonly RegistrationFactory _registrationFactory;
private readonly List<IRegistrationBase> _registrations = new List<IRegistrationBase>();
private readonly List<(Type type, object instance)> _singletons = new List<(Type, object)>();
private readonly List<(Type type, Type scope, ConditionalWeakTable<object, object> instances)> _multitons = new List<(Type, Type, ConditionalWeakTable<object, object>)>();
/// <summary>
/// The constructor of the <see cref="IocContainer"/>
/// </summary>
public IocContainer()
{
_registrationFactory = new RegistrationFactory(this);
}
/// <summary>
/// Install the given installers for the current <see cref="IocContainer"/>
/// </summary>
@ -39,12 +52,94 @@ namespace LightweightIocContainer
return this;
}
/// <summary>
/// Register an Interface with a Type that implements it/>
/// </summary>
/// <typeparam name="TInterface">The Interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
public void Register<TInterface, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface
{
Register(_registrationFactory.Register<TInterface, TImplementation>(lifestyle));
}
/// <summary>
/// Register a <see cref="Type"/> without an interface/>
/// </summary>
/// <typeparam name="TImplementation">The <see cref="Type"/> to register</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
public void Register<TImplementation>(Lifestyle lifestyle = Lifestyle.Transient)
{
Register(_registrationFactory.Register<TImplementation>(lifestyle));
}
/// <summary>
/// Register an Interface with a Type that implements it as a multiton/>
/// </summary>
/// <typeparam name="TInterface">The Interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam>
public void Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface
{
Register(_registrationFactory.Register<TInterface, TImplementation, TScope>());
}
/// <summary>
/// Register an Interface with a Type that implements it/>
/// </summary>
/// <param name="tInterface">The Interface to register</param>
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
public void Register(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient)
{
Register(_registrationFactory.Register(tInterface, tImplementation, lifestyle));
}
/// <summary>
/// Register a <see cref="Type"/> without an interface/>
/// </summary>
/// <param name="tImplementation">The <see cref="Type"/> to register</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
public void Register(Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient)
{
Register(_registrationFactory.Register(tImplementation, lifestyle));
}
/// <summary>
/// Register an Interface with a Type that implements it as a multiton/>
/// </summary>
/// <param name="tInterface">The Interface to register</param>
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="tScope">The Type of the multiton scope</param>
public void Register(Type tInterface, Type tImplementation, Type tScope)
{
Register(_registrationFactory.Register(tInterface, tImplementation, tScope));
}
/// <summary>
/// Register an Interface as an abstract typed factory/>
/// </summary>
/// <typeparam name="TFactory">The abstract typed factory to register</typeparam>
public void RegisterFactory<TFactory>()
{
Register(_registrationFactory.RegisterFactory<TFactory>());
}
/// <summary>
/// Register an Interface as an abstract typed factory/>
/// </summary>
/// <param name="tFactory">The abstract typed factory to register</param>
public void RegisterFactory(Type tFactory)
{
Register(_registrationFactory.RegisterFactory(tFactory));
}
/// <summary>
/// Add the <see cref="IRegistrationBase"/> to the the <see cref="IocContainer"/>
/// </summary>
/// <param name="registration">The given <see cref="IRegistrationBase"/></param>
/// <exception cref="MultipleRegistrationException">The <see cref="Type"/> is already registered in this <see cref="IocContainer"/></exception>
public void Register(IRegistrationBase registration)
private void Register(IRegistrationBase registration)
{
//if type is already registered
if (_registrations.Any(r => r.InterfaceType == registration.InterfaceType))

@ -217,12 +217,63 @@
<param name="installers">The given <see cref="T:LightweightIocContainer.Interfaces.Installers.IIocInstaller"/>s</param>
<returns>An instance of the current <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></returns>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register(LightweightIocContainer.Interfaces.Registrations.IRegistrationBase)">
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register``2(LightweightIocContainer.Lifestyle)">
<summary>
Add the <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase"/> to the the <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/>
Register an Interface with a Type that implements it/>
</summary>
<param name="registration">The given <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase"/></param>
<exception cref="T:LightweightIocContainer.Exceptions.MultipleRegistrationException">The <see cref="T:System.Type"/> is already registered in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></exception>
<typeparam name="TInterface">The Interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register``1(LightweightIocContainer.Lifestyle)">
<summary>
Register a <see cref="T:System.Type"/> without an interface/>
</summary>
<typeparam name="TImplementation">The <see cref="T:System.Type"/> to register</typeparam>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register``3">
<summary>
Register an Interface with a Type that implements it as a multiton/>
</summary>
<typeparam name="TInterface">The Interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<typeparam name="TScope">The Type of the multiton scope</typeparam>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register(System.Type,System.Type,LightweightIocContainer.Lifestyle)">
<summary>
Register an Interface with a Type that implements it/>
</summary>
<param name="tInterface">The Interface to register</param>
<param name="tImplementation">The Type that implements the interface</param>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register(System.Type,LightweightIocContainer.Lifestyle)">
<summary>
Register a <see cref="T:System.Type"/> without an interface/>
</summary>
<param name="tImplementation">The <see cref="T:System.Type"/> to register</param>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Register(System.Type,System.Type,System.Type)">
<summary>
Register an Interface with a Type that implements it as a multiton/>
</summary>
<param name="tInterface">The Interface to register</param>
<param name="tImplementation">The Type that implements the interface</param>
<param name="tScope">The Type of the multiton scope</param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.RegisterFactory``1">
<summary>
Register an Interface as an abstract typed factory/>
</summary>
<typeparam name="TFactory">The abstract typed factory to register</typeparam>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.RegisterFactory(System.Type)">
<summary>
Register an Interface as an abstract typed factory/>
</summary>
<param name="tFactory">The abstract typed factory to register</param>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.Resolve``1">
<summary>
@ -353,6 +404,11 @@
The main container that carries all the <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase"/>s and can resolve all the types you'll ever want
</summary>
</member>
<member name="M:LightweightIocContainer.IocContainer.#ctor">
<summary>
The constructor of the <see cref="T:LightweightIocContainer.IocContainer"/>
</summary>
</member>
<member name="M:LightweightIocContainer.IocContainer.Install(LightweightIocContainer.Interfaces.Installers.IIocInstaller[])">
<summary>
Install the given installers for the current <see cref="T:LightweightIocContainer.IocContainer"/>
@ -360,6 +416,64 @@
<param name="installers">The given <see cref="T:LightweightIocContainer.Interfaces.Installers.IIocInstaller"/>s</param>
<returns>An instance of the current <see cref="T:LightweightIocContainer.IocContainer"/></returns>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register``2(LightweightIocContainer.Lifestyle)">
<summary>
Register an Interface with a Type that implements it/>
</summary>
<typeparam name="TInterface">The Interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register``1(LightweightIocContainer.Lifestyle)">
<summary>
Register a <see cref="T:System.Type"/> without an interface/>
</summary>
<typeparam name="TImplementation">The <see cref="T:System.Type"/> to register</typeparam>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register``3">
<summary>
Register an Interface with a Type that implements it as a multiton/>
</summary>
<typeparam name="TInterface">The Interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<typeparam name="TScope">The Type of the multiton scope</typeparam>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register(System.Type,System.Type,LightweightIocContainer.Lifestyle)">
<summary>
Register an Interface with a Type that implements it/>
</summary>
<param name="tInterface">The Interface to register</param>
<param name="tImplementation">The Type that implements the interface</param>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register(System.Type,LightweightIocContainer.Lifestyle)">
<summary>
Register a <see cref="T:System.Type"/> without an interface/>
</summary>
<param name="tImplementation">The <see cref="T:System.Type"/> to register</param>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> for this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IDefaultRegistration`1"/></param>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register(System.Type,System.Type,System.Type)">
<summary>
Register an Interface with a Type that implements it as a multiton/>
</summary>
<param name="tInterface">The Interface to register</param>
<param name="tImplementation">The Type that implements the interface</param>
<param name="tScope">The Type of the multiton scope</param>
</member>
<member name="M:LightweightIocContainer.IocContainer.RegisterFactory``1">
<summary>
Register an Interface as an abstract typed factory/>
</summary>
<typeparam name="TFactory">The abstract typed factory to register</typeparam>
</member>
<member name="M:LightweightIocContainer.IocContainer.RegisterFactory(System.Type)">
<summary>
Register an Interface as an abstract typed factory/>
</summary>
<param name="tFactory">The abstract typed factory to register</param>
</member>
<member name="M:LightweightIocContainer.IocContainer.Register(LightweightIocContainer.Interfaces.Registrations.IRegistrationBase)">
<summary>
Add the <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase"/> to the the <see cref="T:LightweightIocContainer.IocContainer"/>
@ -604,20 +718,18 @@
<param name="tScope">The Type of the multiton scope</param>
<returns>A new created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IMultitonRegistration`1"/> with the given parameters</returns>
</member>
<member name="M:LightweightIocContainer.Registrations.RegistrationFactory.RegisterFactory``1(LightweightIocContainer.Interfaces.IIocContainer)">
<member name="M:LightweightIocContainer.Registrations.RegistrationFactory.RegisterFactory``1">
<summary>
Register an Interface as an abstract typed factory and create a <see cref="T:LightweightIocContainer.Interfaces.Registrations.ITypedFactoryRegistration`1"/>
</summary>
<typeparam name="TFactory">The abstract typed factory to register</typeparam>
<param name="container">The current <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></param>
<returns>A new created <see cref="T:LightweightIocContainer.Interfaces.Registrations.ITypedFactoryRegistration`1"/> with the given parameters</returns>
</member>
<member name="M:LightweightIocContainer.Registrations.RegistrationFactory.RegisterFactory(System.Type,LightweightIocContainer.Interfaces.IIocContainer)">
<member name="M:LightweightIocContainer.Registrations.RegistrationFactory.RegisterFactory(System.Type)">
<summary>
Register an Interface as an abstract typed factory and create a <see cref="T:LightweightIocContainer.Interfaces.Registrations.ITypedFactoryRegistration`1"/>
</summary>
<param name="tFactory">The abstract typed factory to register</param>
<param name="container">The current <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></param>
<returns>A new created <see cref="T:LightweightIocContainer.Interfaces.Registrations.ITypedFactoryRegistration`1"/> with the given parameters</returns>
</member>
<member name="T:LightweightIocContainer.Registrations.TypedFactoryRegistration`1">

@ -13,8 +13,15 @@ namespace LightweightIocContainer.Registrations
/// <summary>
/// A factory to register interfaces and factories in an <see cref="IIocInstaller"/> and create the needed <see cref="IRegistrationBase"/>s
/// </summary>
public static class RegistrationFactory
internal class RegistrationFactory
{
private readonly IIocContainer _iocContainer;
internal RegistrationFactory(IIocContainer container)
{
_iocContainer = container;
}
/// <summary>
/// Register an Interface with a Type that implements it and create a <see cref="IDefaultRegistration{TInterface}"/>
/// </summary>
@ -22,7 +29,7 @@ namespace LightweightIocContainer.Registrations
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="IDefaultRegistration{TInterface}"/> with the given parameters</returns>
public static IDefaultRegistration<TInterface> Register<TInterface, TImplementation>(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface
public IDefaultRegistration<TInterface> Register<TInterface, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface
{
return new DefaultRegistration<TInterface>(typeof(TInterface), typeof(TImplementation), lifestyle);
}
@ -33,9 +40,9 @@ namespace LightweightIocContainer.Registrations
/// <typeparam name="TImplementation">The <see cref="Type"/> to register</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="IDefaultRegistration{TInterface}"/> with the given parameters</returns>
public static IDefaultRegistration<TImplementation> Register<TImplementation>(Lifestyle lifestyle = Lifestyle.Transient)
public IDefaultRegistration<TImplementation> Register<TImplementation>(Lifestyle lifestyle)
{
if (typeof(TImplementation).IsInterface)
if (typeof(TImplementation).IsInterface) //TODO: handle `Instance` case when an instance is given
throw new InvalidRegistrationException("Can't register an interface without its implementation type.");
return Register<TImplementation, TImplementation>(lifestyle);
@ -48,7 +55,7 @@ namespace LightweightIocContainer.Registrations
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam>
/// <returns>A new created <see cref="IMultitonRegistration{TInterface}"/> with the given parameters</returns>
public static IMultitonRegistration<TInterface> Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface
public IMultitonRegistration<TInterface> Register<TInterface, TImplementation, TScope>() where TImplementation : TInterface
{
return new MultitonRegistration<TInterface>(typeof(TInterface), typeof(TImplementation), typeof(TScope));
}
@ -60,7 +67,7 @@ namespace LightweightIocContainer.Registrations
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="IDefaultRegistration{TInterface}"/> with the given parameters</returns>
public static IRegistrationBase Register(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient)
public IRegistrationBase Register(Type tInterface, Type tImplementation, Lifestyle lifestyle)
{
Type defaultRegistrationType = typeof(DefaultRegistration<>).MakeGenericType(tInterface);
return (IRegistrationBase)Activator.CreateInstance(defaultRegistrationType, tInterface, tImplementation, lifestyle);
@ -72,9 +79,9 @@ namespace LightweightIocContainer.Registrations
/// <param name="tImplementation">The <see cref="Type"/> to register</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IDefaultRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="IDefaultRegistration{TInterface}"/> with the given parameters</returns>
public static IRegistrationBase Register(Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient)
public IRegistrationBase Register(Type tImplementation, Lifestyle lifestyle)
{
if (tImplementation.IsInterface)
if (tImplementation.IsInterface) //TODO: handle `Instance` case when an instance is given
throw new InvalidRegistrationException("Can't register an interface without its implementation type.");
return Register(tImplementation, tImplementation, lifestyle);
@ -87,7 +94,7 @@ namespace LightweightIocContainer.Registrations
/// <param name="tImplementation">The Type that implements the interface</param>
/// <param name="tScope">The Type of the multiton scope</param>
/// <returns>A new created <see cref="IMultitonRegistration{TInterface}"/> with the given parameters</returns>
public static IRegistrationBase Register(Type tInterface, Type tImplementation, Type tScope)
public IRegistrationBase Register(Type tInterface, Type tImplementation, Type tScope)
{
Type multitonRegistrationType = typeof(MultitonRegistration<>).MakeGenericType(tInterface);
return (IRegistrationBase)Activator.CreateInstance(multitonRegistrationType, tInterface, tImplementation, tScope);
@ -97,23 +104,21 @@ namespace LightweightIocContainer.Registrations
/// Register an Interface as an abstract typed factory and create a <see cref="ITypedFactoryRegistration{TFactory}"/>
/// </summary>
/// <typeparam name="TFactory">The abstract typed factory to register</typeparam>
/// <param name="container">The current <see cref="IIocContainer"/></param>
/// <returns>A new created <see cref="ITypedFactoryRegistration{TFactory}"/> with the given parameters</returns>
public static ITypedFactoryRegistration<TFactory> RegisterFactory<TFactory>(IIocContainer container) //TODO: Find a nicer way to inject the container into `TypedFactoryRegistration`
public ITypedFactoryRegistration<TFactory> RegisterFactory<TFactory>()
{
return new TypedFactoryRegistration<TFactory>(typeof(TFactory), container);
return new TypedFactoryRegistration<TFactory>(typeof(TFactory), _iocContainer);
}
/// <summary>
/// Register an Interface as an abstract typed factory and create a <see cref="ITypedFactoryRegistration{TFactory}"/>
/// </summary>
/// <param name="tFactory">The abstract typed factory to register</param>
/// <param name="container">The current <see cref="IIocContainer"/></param>
/// <returns>A new created <see cref="ITypedFactoryRegistration{TFactory}"/> with the given parameters</returns>
public static IRegistrationBase RegisterFactory(Type tFactory, IIocContainer container)
public IRegistrationBase RegisterFactory(Type tFactory)
{
Type factoryRegistrationType = typeof(TypedFactoryRegistration<>).MakeGenericType(tFactory);
return (IRegistrationBase)Activator.CreateInstance(factoryRegistrationType, tFactory, container);
return (IRegistrationBase)Activator.CreateInstance(factoryRegistrationType, tFactory, _iocContainer);
}
}
}

@ -25,7 +25,7 @@ namespace Test.LightweightIocContainer
{
public void Install(IIocContainer container)
{
container.Register(new Mock<IRegistrationBase>().Object);
container.Register<Mock<IRegistrationBase>>();
}
}
@ -54,7 +54,7 @@ namespace Test.LightweightIocContainer
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(assemblyMock.Object);
assemblyInstaller.Install(iocContainerMock.Object);
iocContainerMock.Verify(ioc => ioc.Register(It.IsAny<IRegistrationBase>()), Times.Once);
iocContainerMock.Verify(ioc => ioc.Register<It.IsSubtype<Mock<IRegistrationBase>>>(It.IsAny<Lifestyle>()), Times.Once);
}
[Test]

@ -3,8 +3,11 @@
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
using LightweightIocContainer.Registrations;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
@ -33,7 +36,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestOnCreate()
{
IDefaultRegistration<ITest> testRegistration = RegistrationFactory.Register<ITest, Test>().OnCreate(t => t.DoSomething());
RegistrationFactory registrationFactory = new RegistrationFactory(new Mock<IIocContainer>().Object);
IDefaultRegistration<ITest> testRegistration = registrationFactory.Register<ITest, Test>(Lifestyle.Transient).OnCreate(t => t.DoSomething());
ITest test = new Test();

@ -3,7 +3,6 @@ using LightweightIocContainer;
using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Registrations;
using Moq;
using NUnit.Framework;
@ -116,52 +115,52 @@ namespace Test.LightweightIocContainer
[Test]
public void TestRegister()
{
Assert.DoesNotThrow(() => _iocContainer.Register(RegistrationFactory.Register(typeof(ITest), typeof(Test))));
Assert.DoesNotThrow(() => _iocContainer.Register(typeof(ITest), typeof(Test)));
}
[Test]
public void TestRegisterTypeWithoutInterface()
{
Assert.DoesNotThrow(() => _iocContainer.Register(RegistrationFactory.Register(typeof(Test))));
Assert.DoesNotThrow(() => _iocContainer.Register(typeof(Test)));
}
[Test]
public void TestRegisterMultiton()
{
Assert.DoesNotThrow(() => _iocContainer.Register(RegistrationFactory.Register(typeof(ITest), typeof(Test), typeof(MultitonScope))));
Assert.DoesNotThrow(() => _iocContainer.Register(typeof(ITest), typeof(Test), typeof(MultitonScope)));
}
[Test]
public void TestRegisterFactory()
{
Assert.DoesNotThrow(() => _iocContainer.Register(RegistrationFactory.RegisterFactory(typeof(ITestFactory), _iocContainer)));
Assert.DoesNotThrow(() => _iocContainer.RegisterFactory(typeof(ITestFactory)));
}
[Test]
public void TestRegisterMultiple()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>()));
_iocContainer.Register<ITest, Test>();
MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register<ITest, TestConstructor>());
Assert.AreEqual(typeof(ITest), exception.Type);
}
[Test]
public void TestRegisterInterfaceWithoutImplementation()
{
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(RegistrationFactory.Register<ITest>()));
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(RegistrationFactory.Register(typeof(ITest))));
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register<ITest>());
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(typeof(ITest)));
}
[Test]
public void TestRegisterFactoryWithoutCreate()
{
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactoryNoCreate>(_iocContainer)));
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.RegisterFactory<ITestFactoryNoCreate>());
}
[Test]
public void TestRegisterFactoryClearMultitonsNonGeneric()
{
Assert.Throws<IllegalAbstractMethodCreationException>(() => _iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactoryNonGenericClear>(_iocContainer)));
Assert.Throws<IllegalAbstractMethodCreationException>(() => _iocContainer.RegisterFactory<ITestFactoryNonGenericClear>());
}
[Test]
@ -174,7 +173,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolve()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register<ITest, Test>();
ITest resolvedTest = _iocContainer.Resolve<ITest>();
@ -184,7 +183,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveWithoutInterface()
{
_iocContainer.Register(RegistrationFactory.Register<Test>());
_iocContainer.Register<Test>();
Test resolvedTest = _iocContainer.Resolve<Test>();
@ -194,7 +193,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveWithParams()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>());
_iocContainer.Register<ITest, TestConstructor>();
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test", new Test());
@ -204,8 +203,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveWithMissingParam()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>());
_iocContainer.Register(RegistrationFactory.Register<Test, Test>()); //this registration is abnormal and should only be used in unit tests
_iocContainer.Register<ITest, TestConstructor>();
_iocContainer.Register<Test, Test>(); //this registration is abnormal and should only be used in unit tests
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test");
@ -215,7 +214,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveReflection()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register<ITest, Test>();
object resolvedTest = _iocContainer.Resolve(typeof(ITest), null);
@ -225,7 +224,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveSingleton()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>(Lifestyle.Singleton));
_iocContainer.Register<ITest, Test>(Lifestyle.Singleton);
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
@ -236,7 +235,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveMultiton()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test, MultitonScope>());
_iocContainer.Register<ITest, Test, MultitonScope>();
MultitonScope scope1 = new MultitonScope();
MultitonScope scope2 = new MultitonScope();
@ -253,7 +252,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveMultitonNoArgs()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test, MultitonScope>());
_iocContainer.Register<ITest, Test, MultitonScope>();
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception.Type);
@ -262,7 +261,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveMultitonWrongArgs()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test, MultitonScope>());
_iocContainer.Register<ITest, Test, MultitonScope>();
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>(new object()));
Assert.AreEqual(typeof(ITest), exception.Type);
@ -271,7 +270,7 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveTransient()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register<ITest, Test>();
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
@ -282,8 +281,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveFactory()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, Test>();
_iocContainer.RegisterFactory<ITestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
@ -293,8 +292,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveFromFactory()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, Test>();
_iocContainer.RegisterFactory<ITestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
@ -305,9 +304,9 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveFromFactoryWithParams()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>());
_iocContainer.Register(RegistrationFactory.Register<Test, Test>()); //this registration is abnormal and should only be used in unit tests
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, TestConstructor>();
_iocContainer.Register<Test, Test>(); //this registration is abnormal and should only be used in unit tests
_iocContainer.RegisterFactory<ITestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create("Test");
@ -318,9 +317,9 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveFromFactoryWithDefaultParamCreate()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>());
_iocContainer.Register(RegistrationFactory.Register<Test, Test>()); //this registration is abnormal and should only be used in unit tests
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, TestConstructor>();
_iocContainer.Register<Test, Test>(); //this registration is abnormal and should only be used in unit tests
_iocContainer.RegisterFactory<ITestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.CreateTest();
@ -331,9 +330,9 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveFromFactoryWithDefaultParamCtor()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, TestConstructor>());
_iocContainer.Register(RegistrationFactory.Register<Test, Test>()); //this registration is abnormal and should only be used in unit tests
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, TestConstructor>();
_iocContainer.Register<Test, Test>(); //this registration is abnormal and should only be used in unit tests
_iocContainer.RegisterFactory<ITestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
@ -344,8 +343,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveMultitonFromFactory()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test, MultitonScope>());
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, Test, MultitonScope>();
_iocContainer.RegisterFactory<ITestFactory>();
MultitonScope scope1 = new MultitonScope();
MultitonScope scope2 = new MultitonScope();
@ -364,8 +363,8 @@ namespace Test.LightweightIocContainer
[Test]
public void TestResolveMultitonFromFactoryClearInstances()
{
_iocContainer.Register(RegistrationFactory.Register<ITest, Test, MultitonScope>());
_iocContainer.Register(RegistrationFactory.RegisterFactory<ITestFactory>(_iocContainer));
_iocContainer.Register<ITest, Test, MultitonScope>();
_iocContainer.RegisterFactory<ITestFactory>();
MultitonScope scope1 = new MultitonScope();
MultitonScope scope2 = new MultitonScope();
@ -395,10 +394,10 @@ namespace Test.LightweightIocContainer
{
Assert.False(_iocContainer.IsTypeRegistered<ITest>());
_iocContainer.Register(RegistrationFactory.Register<ITest, Test>());
_iocContainer.Register<ITest, Test>();
Assert.True(_iocContainer.IsTypeRegistered<ITest>());
_iocContainer.Register(RegistrationFactory.Register<Test>());
_iocContainer.Register<Test>();
Assert.True(_iocContainer.IsTypeRegistered<Test>());
}
}

@ -8,7 +8,7 @@
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3" />
<PackageReference Include="Moq" Version="4.12.0" />
<PackageReference Include="Moq" Version="4.13.0" />
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />

Loading…
Cancel
Save