Merge pull request #47 from SimonG96/OpenGenericRegistration

#45: add multipleMultitonRegistration
pull/53/head
Simon G 5 years ago committed by GitHub
commit 6590efb388
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .idea/.idea.LightweightIocContainer/.idea/modules.xml
  2. 10
      LightweightIocContainer/Interfaces/IIocContainer.cs
  3. 17
      LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs
  4. 2
      LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs
  5. 26
      LightweightIocContainer/IocContainer.cs
  6. 67
      LightweightIocContainer/LightweightIocContainer.xml
  7. 59
      LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs
  8. 13
      LightweightIocContainer/Registrations/RegistrationFactory.cs
  9. 102
      Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs

@ -2,7 +2,7 @@
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.LightweightIocContainer/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.LightweightIocContainer/riderModule.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.LightweightIocContainer/.idea/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.LightweightIocContainer/.idea/riderModule.iml" />
</modules>
</component>
</project>

@ -101,6 +101,16 @@ namespace LightweightIocContainer.Interfaces
/// <returns>The created <see cref="IRegistration"/></returns>
IMultitonRegistration<TInterface, TImplementation> RegisterMultiton<TInterface, TImplementation, TScope>() where TImplementation : TInterface;
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them as a multiton
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam>
/// <returns>The created <see cref="IRegistration"/></returns>
IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> RegisterMultiton<TInterface1, TInterface2, TImplementation, TScope>() where TImplementation : TInterface1, TInterface2;
/// <summary>
/// Register an Interface as an abstract typed factory
/// </summary>

@ -0,0 +1,17 @@
// Author: Gockner, Simon
// Created: 2020-11-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Interfaces.Registrations
{
/// <summary>
/// An <see cref="IRegistrationBase{TInterface}"/> to register multiple interfaces for on implementation type that implements them as a multiton
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> : IMultitonRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
{
}
}

@ -17,7 +17,7 @@ namespace LightweightIocContainer.Interfaces.Registrations
/// <summary>
/// A base <see cref="IMultitonRegistration{TInterface}"/> without implementation
/// </summary>
public interface IMultitonRegistration<TInterface> : IRegistrationBase<TInterface>, IMultitonRegistration
public interface IMultitonRegistration<TInterface> : ITypedRegistrationBase<TInterface>, IMultitonRegistration
{
/// <summary>
/// The <see cref="Type"/> of the multiton scope

@ -193,6 +193,22 @@ namespace LightweightIocContainer
return registration;
}
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them as a multiton
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TImplementation">The Type that implements the interface</typeparam>
/// <typeparam name="TScope">The Type of the multiton scope</typeparam>
/// <returns>The created <see cref="IRegistration"/></returns>
public IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> RegisterMultiton<TInterface1, TInterface2, TImplementation, TScope>() where TImplementation : TInterface1, TInterface2
{
IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> registration = _registrationFactory.RegisterMultiton<TInterface1, TInterface2, TImplementation, TScope>();
Register(registration);
return registration;
}
/// <summary>
/// Register an Interface as an abstract typed factory
/// </summary>
@ -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<object, object> weakTable = new ConditionalWeakTable<object, object>();
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
/// <typeparam name="T">The <see cref="Type"/> to clear the multiton instances</typeparam>
public void ClearMultitonInstances<T>()
{
var multitonInstance = _multitons.FirstOrDefault(m => m.type == typeof(T));
IRegistration registration = FindRegistration<T>();
if (!(registration is IMultitonRegistration<T> 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)

@ -447,6 +447,16 @@
<typeparam name="TScope">The Type of the multiton scope</typeparam>
<returns>The created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/></returns>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.RegisterMultiton``4">
<summary>
Register multiple interfaces for a <see cref="T:System.Type"/> that implements them as a multiton
</summary>
<typeparam name="TInterface1">The base interface to register</typeparam>
<typeparam name="TInterface2">A second interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<typeparam name="TScope">The Type of the multiton scope</typeparam>
<returns>The created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/></returns>
</member>
<member name="M:LightweightIocContainer.Interfaces.IIocContainer.RegisterFactory``1">
<summary>
Register an Interface as an abstract typed factory
@ -575,6 +585,14 @@
The Lifestyle of Instances that are created with this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/>
</summary>
</member>
<member name="T:LightweightIocContainer.Interfaces.Registrations.IMultipleMultitonRegistration`3">
<summary>
An <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase`1"/> to register multiple interfaces for on implementation type that implements them as a multiton
</summary>
<typeparam name="TInterface1">The first interface</typeparam>
<typeparam name="TInterface2">The second interface</typeparam>
<typeparam name="TImplementation">The implementation</typeparam>
</member>
<member name="T:LightweightIocContainer.Interfaces.Registrations.IMultipleRegistration`2">
<summary>
The base interface for every <see cref="T:LightweightIocContainer.Interfaces.Registrations.IMultipleRegistration`3"/> to register multiple interfaces
@ -827,6 +845,16 @@
<typeparam name="TScope">The Type of the multiton scope</typeparam>
<returns>The created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/></returns>
</member>
<member name="M:LightweightIocContainer.IocContainer.RegisterMultiton``4">
<summary>
Register multiple interfaces for a <see cref="T:System.Type"/> that implements them as a multiton
</summary>
<typeparam name="TInterface1">The base interface to register</typeparam>
<typeparam name="TInterface2">A second interface to register</typeparam>
<typeparam name="TImplementation">The Type that implements the interface</typeparam>
<typeparam name="TScope">The Type of the multiton scope</typeparam>
<returns>The created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/></returns>
</member>
<member name="M:LightweightIocContainer.IocContainer.RegisterFactory``1">
<summary>
Register an Interface as an abstract typed factory
@ -989,6 +1017,35 @@
<param name="implementationType">The <see cref="T:System.Type"/> of the implementation</param>
<param name="lifestyle">The <see cref="T:LightweightIocContainer.Lifestyle"/> of the <see cref="T:LightweightIocContainer.Registrations.RegistrationBase`1"/></param>
</member>
<member name="T:LightweightIocContainer.Registrations.MultipleMultitonRegistration`3">
<summary>
An <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase`1"/> to register multiple interfaces for on implementation type that implements them as a multiton
</summary>
<typeparam name="TInterface1">The first interface</typeparam>
<typeparam name="TInterface2">The second interface</typeparam>
<typeparam name="TImplementation">The implementation</typeparam>
</member>
<member name="M:LightweightIocContainer.Registrations.MultipleMultitonRegistration`3.#ctor(System.Type,System.Type,System.Type,System.Type)">
<summary>
An <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistrationBase`1"/> to register multiple interfaces for on implementation type that implements them as a multiton
</summary>
<param name="interfaceType1">The <see cref="T:System.Type"/> of the first interface</param>
<param name="interfaceType2">The <see cref="T:System.Type"/> of the second interface</param>
<param name="implementationType">The <see cref="T:System.Type"/> of the implementation</param>
<param name="scope">The <see cref="T:System.Type"/> of the multiton scope</param>
</member>
<member name="P:LightweightIocContainer.Registrations.MultipleMultitonRegistration`3.Registrations">
<summary>
A <see cref="T:System.Collections.Generic.List`1"/> of <see cref="T:LightweightIocContainer.Interfaces.Registrations.IRegistration"/>s that are registered within this <see cref="T:LightweightIocContainer.Interfaces.Registrations.IMultipleRegistration`2"/>
</summary>
</member>
<member name="M:LightweightIocContainer.Registrations.MultipleMultitonRegistration`3.OnCreate(System.Action{`2})">
<summary>
Pass an <see cref="T:System.Action`1"/> that will be invoked when an instance of this type is created
</summary>
<param name="action">The <see cref="T:System.Action`1"/></param>
<returns>The current instance of this <see cref="T:LightweightIocContainer.Interfaces.Registrations.ITypedRegistrationBase`2"/></returns>
</member>
<member name="T:LightweightIocContainer.Registrations.MultipleRegistration`2">
<summary>
The base class for every <see cref="T:LightweightIocContainer.Interfaces.Registrations.IMultipleRegistration`3"/> to register multiple interfaces
@ -1299,6 +1356,16 @@
<typeparam name="TScope">The Type of the multiton scope</typeparam>
<returns>A new created <see cref="T:LightweightIocContainer.Interfaces.Registrations.IMultitonRegistration`2"/> with the given parameters</returns>
</member>
<member name="M:LightweightIocContainer.Registrations.RegistrationFactory.RegisterMultiton``4">
<summary>
Register multiple interfaces for a <see cref="T:System.Type"/> that implements them as a multiton
</summary>
<typeparam name="TInterface1">The base interface to register</typeparam>
<typeparam name="TInterface2">A second interface to register</typeparam>
<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="T:LightweightIocContainer.Interfaces.Registrations.IMultipleMultitonRegistration`3"/> with the given parameters</returns>
</member>
<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"/>

@ -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
{
/// <summary>
/// An <see cref="IRegistrationBase{TInterface}"/> to register multiple interfaces for on implementation type that implements them as a multiton
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public class MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> : MultitonRegistration<TInterface1, TImplementation>, IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
{
/// <summary>
/// An <see cref="IRegistrationBase{TInterface}"/> to register multiple interfaces for on implementation type that implements them as a multiton
/// </summary>
/// <param name="interfaceType1">The <see cref="Type"/> of the first interface</param>
/// <param name="interfaceType2">The <see cref="Type"/> of the second interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="scope">The <see cref="Type"/> of the multiton scope</param>
public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope)
: base(interfaceType1, implementationType, scope)
{
Registrations = new List<IRegistration>()
{
new MultitonRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, scope),
new MultitonRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, scope)
};
}
/// <summary>
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="IMultipleRegistration{TInterface1,TImplementation}"/>
/// </summary>
public List<IRegistration> Registrations { get; }
/// <summary>
/// Pass an <see cref="Action{T}"/> that will be invoked when an instance of this type is created
/// </summary>
/// <param name="action">The <see cref="Action{T}"/></param>
/// <returns>The current instance of this <see cref="ITypedRegistrationBase{TInterface,TImplementation}"/></returns>
public override ITypedRegistrationBase<TInterface1, TImplementation> OnCreate(Action<TImplementation> action)
{
foreach (var registration in Registrations)
{
if (registration is IMultitonRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is IMultitonRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}
}

@ -119,6 +119,19 @@ namespace LightweightIocContainer.Registrations
return new MultitonRegistration<TInterface, TImplementation>(typeof(TInterface), typeof(TImplementation), typeof(TScope));
}
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them as a multiton
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <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="IMultipleMultitonRegistration{TInterface1,TInterface2,TImplementation}"/> with the given parameters</returns>
public IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> RegisterMultiton<TInterface1, TInterface2, TImplementation, TScope>() where TImplementation : TInterface1, TInterface2
{
return new MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope));
}
/// <summary>
/// Register an Interface as an abstract typed factory and create a <see cref="ITypedFactoryRegistration{TFactory}"/>
/// </summary>

@ -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<IProvider, ITest, Test, MultitonScope>();
MultitonScope scope = new MultitonScope();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
IProvider provider = _iocContainer.Resolve<IProvider>(scope);
Assert.NotNull(provider);
Assert.AreEqual(test, provider);
Assert.AreSame(test, provider);
}
[Test]
public void TestRegisterAndResolveMultipleMultitonRegistrationWithDifferentScope()
{
_iocContainer.RegisterMultiton<IProvider, ITest, Test, MultitonScope>();
MultitonScope scope = new MultitonScope();
MultitonScope differentScope = new MultitonScope();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
IProvider provider = _iocContainer.Resolve<IProvider>(differentScope);
Assert.NotNull(provider);
Assert.AreNotEqual(test, provider);
Assert.AreNotSame(test, provider);
}
[Test]
public void TestMultipleMultitonRegistrationOnCreate()
{
_iocContainer.RegisterMultiton<IProvider, ITest, Test, MultitonScope>().OnCreate(t => t.DoSomething(1));
MultitonScope scope = new MultitonScope();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
Assert.AreEqual(1, test.Number);
IProvider provider = _iocContainer.Resolve<IProvider>(scope);
Assert.NotNull(provider);
Assert.AreEqual(1, provider.Number);
Assert.AreEqual(test, provider);
Assert.AreSame(test, provider);
}
}
}
Loading…
Cancel
Save