- use file scoped namespaces

pull/59/head
Simon G 3 years ago
parent e5b984a058
commit 430f58e1c4
  1. 29
      LightweightIocContainer/ActionExtension.cs
  2. 97
      LightweightIocContainer/EnumerableExtension.cs
  3. 71
      LightweightIocContainer/Exceptions/CircularDependencyException.cs
  4. 31
      LightweightIocContainer/Exceptions/ConstructorNotMatchingException.cs
  5. 19
      LightweightIocContainer/Exceptions/GenericMethodNotFoundException.cs
  6. 31
      LightweightIocContainer/Exceptions/IllegalAbstractMethodCreationException.cs
  7. 19
      LightweightIocContainer/Exceptions/InternalResolveException.cs
  8. 19
      LightweightIocContainer/Exceptions/InvalidFactoryRegistrationException.cs
  9. 19
      LightweightIocContainer/Exceptions/InvalidRegistrationException.cs
  10. 53
      LightweightIocContainer/Exceptions/IocContainerException.cs
  11. 29
      LightweightIocContainer/Exceptions/MultipleRegistrationException.cs
  12. 31
      LightweightIocContainer/Exceptions/MultitonResolveException.cs
  13. 43
      LightweightIocContainer/Exceptions/NoMatchingConstructorFoundException.cs
  14. 29
      LightweightIocContainer/Exceptions/NoPublicConstructorFoundException.cs
  15. 29
      LightweightIocContainer/Exceptions/TypeNotRegisteredException.cs
  16. 19
      LightweightIocContainer/Exceptions/UnknownRegistrationException.cs
  17. 13
      LightweightIocContainer/Factories/CustomTypedFactory.cs
  18. 205
      LightweightIocContainer/Factories/TypedFactory.cs
  19. 29
      LightweightIocContainer/Factories/TypedFactoryBase.cs
  20. 81
      LightweightIocContainer/GenericMethodCaller.cs
  21. 57
      LightweightIocContainer/Installers/AssemblyInstaller.cs
  22. 37
      LightweightIocContainer/Installers/FromAssembly.cs
  23. 35
      LightweightIocContainer/Interfaces/Factories/ITypedFactory.cs
  24. 53
      LightweightIocContainer/Interfaces/IIocContainer.cs
  25. 35
      LightweightIocContainer/Interfaces/IIocResolver.cs
  26. 17
      LightweightIocContainer/Interfaces/Installers/IAssemblyInstaller.cs
  27. 19
      LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs
  28. 43
      LightweightIocContainer/Interfaces/Registrations/Fluent/IOnCreate.cs
  29. 49
      LightweightIocContainer/Interfaces/Registrations/Fluent/IWithFactory.cs
  30. 57
      LightweightIocContainer/Interfaces/Registrations/Fluent/IWithParameters.cs
  31. 17
      LightweightIocContainer/Interfaces/Registrations/ILifestyleProvider.cs
  32. 19
      LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs
  33. 105
      LightweightIocContainer/Interfaces/Registrations/IMultipleRegistration.cs
  34. 33
      LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs
  35. 13
      LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs
  36. 17
      LightweightIocContainer/Interfaces/Registrations/IRegistration.cs
  37. 13
      LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs
  38. 31
      LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs
  39. 19
      LightweightIocContainer/Interfaces/Registrations/ITypedFactoryRegistration.cs
  40. 29
      LightweightIocContainer/Interfaces/Registrations/ITypedRegistration.cs
  41. 1081
      LightweightIocContainer/IocContainer.cs
  42. 33
      LightweightIocContainer/Lifestyle.cs
  43. 79
      LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs
  44. 383
      LightweightIocContainer/Registrations/MultipleRegistration.cs
  45. 83
      LightweightIocContainer/Registrations/MultitonRegistration.cs
  46. 73
      LightweightIocContainer/Registrations/OpenGenericRegistration.cs
  47. 379
      LightweightIocContainer/Registrations/RegistrationBase.cs
  48. 209
      LightweightIocContainer/Registrations/RegistrationFactory.cs
  49. 91
      LightweightIocContainer/Registrations/SingleTypeRegistration.cs
  50. 43
      LightweightIocContainer/Registrations/TypedFactoryRegistration.cs
  51. 109
      LightweightIocContainer/Registrations/TypedRegistration.cs
  52. 13
      LightweightIocContainer/ResolvePlaceholders/InternalResolvePlaceholder.cs
  53. 47
      LightweightIocContainer/ResolvePlaceholders/InternalToBeResolvedPlaceholder.cs
  54. 19
      LightweightIocContainer/TypeExtension.cs
  55. 133
      LightweightIocContainer/Validation/IocValidator.cs
  56. 53
      Test.LightweightIocContainer/ActionExtensionTest.cs
  57. 87
      Test.LightweightIocContainer/AssemblyInstallerTest.cs
  58. 149
      Test.LightweightIocContainer/EnumerableExtensionTest.cs
  59. 387
      Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs
  60. 271
      Test.LightweightIocContainer/IocContainerInterfaceSegregationTest.cs
  61. 227
      Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs
  62. 215
      Test.LightweightIocContainer/IocContainerRecursionTest.cs
  63. 503
      Test.LightweightIocContainer/IocContainerTest.cs
  64. 245
      Test.LightweightIocContainer/IocValidatorTest.cs
  65. 131
      Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs
  66. 37
      Test.LightweightIocContainer/OnCreateTest.cs
  67. 85
      Test.LightweightIocContainer/OpenGenericRegistrationTest.cs
  68. 117
      Test.LightweightIocContainer/RegistrationBaseTest.cs
  69. 83
      Test.LightweightIocContainer/SingleTypeRegistrationTest.cs

@ -4,23 +4,22 @@
using System;
namespace LightweightIocContainer
namespace LightweightIocContainer;
internal static class ActionExtension
{
internal static class ActionExtension
/// <summary>
/// Convert an <see cref="Action{T2}"/> to an <see cref="Action{T1}"/> of an inherited <see cref="Type"/>
/// </summary>
/// <typeparam name="T1">The <see cref="Type"/> of the <see cref="Action{T1}"/> to convert to, has to be implemented by <typeparamref name="T2"/></typeparam>
/// <typeparam name="T2">The <see cref="Type"/> of the given <see cref="Action{T2}"/>, has to implement <typeparamref name="T1"/></typeparam>
/// <param name="action">The given <see cref="Action{T2}"/> to convert</param>
/// <returns>An <see cref="Action{T1}"/> converted from the given <see cref="Action{T2}"/></returns>
public static Action<T1>? Convert<T1, T2>(this Action<T2>? action) where T1 : T2
{
/// <summary>
/// Convert an <see cref="Action{T2}"/> to an <see cref="Action{T1}"/> of an inherited <see cref="Type"/>
/// </summary>
/// <typeparam name="T1">The <see cref="Type"/> of the <see cref="Action{T1}"/> to convert to, has to be implemented by <typeparamref name="T2"/></typeparam>
/// <typeparam name="T2">The <see cref="Type"/> of the given <see cref="Action{T2}"/>, has to implement <typeparamref name="T1"/></typeparam>
/// <param name="action">The given <see cref="Action{T2}"/> to convert</param>
/// <returns>An <see cref="Action{T1}"/> converted from the given <see cref="Action{T2}"/></returns>
public static Action<T1>? Convert<T1, T2>(this Action<T2>? action) where T1 : T2
{
if (action == null)
return null;
if (action == null)
return null;
return t => action(t);
}
return t => action(t);
}
}

@ -6,61 +6,60 @@ using System;
using System.Collections.Generic;
using System.Linq;
namespace LightweightIocContainer
namespace LightweightIocContainer;
internal static class EnumerableExtension
{
internal static class EnumerableExtension
{
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no elements</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IEnumerable<TSource> source) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(null);
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no elements</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/>, or a new instance of a given <see cref="Type"/> if the <see cref="IEnumerable{T}"/> contains no elements</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IEnumerable<TSource> source) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(null);
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of a given <see cref="Type"/> if no such element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no element that satisfies the given condition</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of the given <see cref="Type"/> if no such element is found</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(predicate);
/// <summary>
/// Returns the first element of a <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of a given <see cref="Type"/> if no such element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to return if the <see cref="IEnumerable{T}"/> contains no element that satisfies the given condition</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> that satisfies a condition, or a new instance of the given <see cref="Type"/> if no such element is found</returns>
public static TSource FirstOrGiven<TSource, TGiven>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) where TGiven : TSource, new() =>
source.TryGetFirst<TSource, TGiven>(predicate);
/// <summary>
/// Tries to get the first element of the given <see cref="IEnumerable{T}"/> or creates a new element of a given <see cref="Type"/> when no element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to create a new element when no fitting element is found</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> or a new instance of the given <see cref="Type"/> when no element is found</returns>
private static TSource TryGetFirst<TSource, TGiven>(this IEnumerable<TSource> source, Func<TSource, bool>? predicate) where TGiven : TSource, new()
/// <summary>
/// Tries to get the first element of the given <see cref="IEnumerable{T}"/> or creates a new element of a given <see cref="Type"/> when no element is found
/// </summary>
/// <typeparam name="TSource">The source <see cref="Type"/> of the <see cref="IEnumerable{T}"/></typeparam>
/// <typeparam name="TGiven">The given <see cref="Type"/> to create a new element when no fitting element is found</typeparam>
/// <param name="source">The given <see cref="IEnumerable{T}"/></param>
/// <param name="predicate">A function to test each element for a condition</param>
/// <returns>The first element of the <see cref="IEnumerable{T}"/> or a new instance of the given <see cref="Type"/> when no element is found</returns>
private static TSource TryGetFirst<TSource, TGiven>(this IEnumerable<TSource> source, Func<TSource, bool>? predicate) where TGiven : TSource, new()
{
try
{
try
{
return predicate == null ? source.First() : source.First(predicate);
}
catch (Exception)
{
return new TGiven();
}
return predicate == null ? source.First() : source.First(predicate);
}
/// <summary>
/// Executes an <see cref="Action{T}"/> for each item in an <see cref="IEnumerable{T}"/>
/// </summary>
/// <param name="enumerable">The <see cref="IEnumerable{T}"/></param>
/// <param name="action">The <see cref="Action{T}"/></param>
/// <typeparam name="T">The <see cref="Type"/> of the items in the <see cref="IEnumerable{T}"/></typeparam>
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
catch (Exception)
{
foreach (T item in enumerable)
action(item);
return new TGiven();
}
}
/// <summary>
/// Executes an <see cref="Action{T}"/> for each item in an <see cref="IEnumerable{T}"/>
/// </summary>
/// <param name="enumerable">The <see cref="IEnumerable{T}"/></param>
/// <param name="action">The <see cref="Action{T}"/></param>
/// <typeparam name="T">The <see cref="Type"/> of the items in the <see cref="IEnumerable{T}"/></typeparam>
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach (T item in enumerable)
action(item);
}
}

@ -7,55 +7,54 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// A circular dependency was detected during <see cref="IocContainer.Resolve{T}()"/>
/// </summary>
internal class CircularDependencyException : IocContainerException
{
/// <summary>
/// A circular dependency was detected during <see cref="IocContainer.Resolve{T}()"/>
/// </summary>
internal class CircularDependencyException : IocContainerException
/// <param name="resolvingType">The currently resolving <see cref="Type"/></param>
/// <param name="resolveStack">The resolve stack at the time the <see cref="CircularDependencyException"/> was thrown</param>
public CircularDependencyException(Type resolvingType, List<Type> resolveStack)
{
/// <summary>
/// A circular dependency was detected during <see cref="IocContainer.Resolve{T}()"/>
/// </summary>
/// <param name="resolvingType">The currently resolving <see cref="Type"/></param>
/// <param name="resolveStack">The resolve stack at the time the <see cref="CircularDependencyException"/> was thrown</param>
public CircularDependencyException(Type resolvingType, List<Type> resolveStack)
{
ResolvingType = resolvingType;
ResolveStack = resolveStack;
}
ResolvingType = resolvingType;
ResolveStack = resolveStack;
}
/// <summary>
/// The currently resolving <see cref="Type"/>
/// </summary>
public Type ResolvingType { get; }
/// <summary>
/// The currently resolving <see cref="Type"/>
/// </summary>
public Type ResolvingType { get; }
/// <summary>
/// The resolve stack at the time the <see cref="CircularDependencyException"/> was thrown
/// </summary>
public List<Type> ResolveStack { get; }
/// <summary>
/// The resolve stack at the time the <see cref="CircularDependencyException"/> was thrown
/// </summary>
public List<Type> ResolveStack { get; }
/// <summary>
/// The exception message
/// </summary>
public override string Message
/// <summary>
/// The exception message
/// </summary>
public override string Message
{
get
{
get
{
StringBuilder message = new($"Circular dependency has been detected when trying to resolve `{ResolvingType}`.\n");
if (!ResolveStack.Any())
return message.ToString();
StringBuilder message = new($"Circular dependency has been detected when trying to resolve `{ResolvingType}`.\n");
if (!ResolveStack.Any())
return message.ToString();
message.Append("Resolve stack that resulted in the circular dependency:\n");
message.Append($"\t`{ResolvingType}` resolved as dependency of\n");
message.Append("Resolve stack that resulted in the circular dependency:\n");
message.Append($"\t`{ResolvingType}` resolved as dependency of\n");
for (int i = ResolveStack.Count - 1; i >= 1 ; i--)
message.Append($"\t`{ResolveStack[i]}` resolved as dependency of\n");
for (int i = ResolveStack.Count - 1; i >= 1 ; i--)
message.Append($"\t`{ResolveStack[i]}` resolved as dependency of\n");
message.Append($"\t`{ResolveStack[0]}` which is the root type being resolved.");
return message.ToString();
}
message.Append($"\t`{ResolveStack[0]}` which is the root type being resolved.");
return message.ToString();
}
}
}

@ -5,25 +5,24 @@
using System;
using System.Reflection;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The constructor does not match the given or resolvable arguments
/// </summary>
internal class ConstructorNotMatchingException : IocContainerException
{
/// <summary>
/// The constructor does not match the given or resolvable arguments
/// </summary>
internal class ConstructorNotMatchingException : IocContainerException
{
/// <summary>
/// The constructor does not match the given or resolvable arguments
/// </summary>
/// <param name="constructor">The constructor that does not match</param>
/// <param name="exception">The inner exception</param>
public ConstructorNotMatchingException(ConstructorInfo constructor, Exception exception)
: base($"Constructor {constructor} does not match the given or resolvable arguments.", exception) =>
Constructor = constructor;
/// <param name="constructor">The constructor that does not match</param>
/// <param name="exception">The inner exception</param>
public ConstructorNotMatchingException(ConstructorInfo constructor, Exception exception)
: base($"Constructor {constructor} does not match the given or resolvable arguments.", exception) =>
Constructor = constructor;
/// <summary>
/// The constructor that does not match
/// </summary>
public ConstructorInfo Constructor { get; }
}
/// <summary>
/// The constructor that does not match
/// </summary>
public ConstructorInfo Constructor { get; }
}

@ -4,21 +4,20 @@
using System;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// Could not find generic method
/// </summary>
internal class GenericMethodNotFoundException : Exception
{
/// <summary>
/// Could not find generic method
/// </summary>
internal class GenericMethodNotFoundException : Exception
/// <param name="functionName">The name of the generic method</param>
public GenericMethodNotFoundException(string functionName)
: base($"Could not find function {functionName}")
{
/// <summary>
/// Could not find generic method
/// </summary>
/// <param name="functionName">The name of the generic method</param>
public GenericMethodNotFoundException(string functionName)
: base($"Could not find function {functionName}")
{
}
}
}

@ -4,25 +4,24 @@
using System.Reflection;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The creation of the abstract method is illegal in its current state
/// </summary>
internal class IllegalAbstractMethodCreationException : IocContainerException
{
/// <summary>
/// The creation of the abstract method is illegal in its current state
/// </summary>
internal class IllegalAbstractMethodCreationException : IocContainerException
{
/// <summary>
/// The creation of the abstract method is illegal in its current state
/// </summary>
/// <param name="message">The exception message</param>
/// <param name="method">The method that is illegal to create</param>
public IllegalAbstractMethodCreationException(string message, MethodInfo method)
: base(message) =>
Method = method;
/// <param name="message">The exception message</param>
/// <param name="method">The method that is illegal to create</param>
public IllegalAbstractMethodCreationException(string message, MethodInfo method)
: base(message) =>
Method = method;
/// <summary>
/// The Method whose creation is illegal
/// </summary>
public MethodInfo Method { get; }
}
/// <summary>
/// The Method whose creation is illegal
/// </summary>
public MethodInfo Method { get; }
}

@ -4,21 +4,20 @@
using LightweightIocContainer.Interfaces;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// An internal Error happened while the <see cref="IIocContainer"/> tried to resolve an instance
/// </summary>
internal class InternalResolveException : IocContainerException
{
/// <summary>
/// An internal Error happened while the <see cref="IIocContainer"/> tried to resolve an instance
/// </summary>
internal class InternalResolveException : IocContainerException
/// <param name="message">The exception message</param>
public InternalResolveException(string message)
: base(message)
{
/// <summary>
/// An internal Error happened while the <see cref="IIocContainer"/> tried to resolve an instance
/// </summary>
/// <param name="message">The exception message</param>
public InternalResolveException(string message)
: base(message)
{
}
}
}

@ -2,21 +2,20 @@
// Created: 2019-05-20
// Copyright(c) 2019 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The registration of a Factory is not valid
/// </summary>
internal class InvalidFactoryRegistrationException : InvalidRegistrationException
{
/// <summary>
/// The registration of a Factory is not valid
/// </summary>
internal class InvalidFactoryRegistrationException : InvalidRegistrationException
/// <param name="message">The exception message</param>
public InvalidFactoryRegistrationException(string message)
: base(message)
{
/// <summary>
/// The registration of a Factory is not valid
/// </summary>
/// <param name="message">The exception message</param>
public InvalidFactoryRegistrationException(string message)
: base(message)
{
}
}
}

@ -2,21 +2,20 @@
// Created: 2019-05-20
// Copyright(c) 2019 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The registration is not valid
/// </summary>
internal class InvalidRegistrationException : IocContainerException
{
/// <summary>
/// The registration is not valid
/// </summary>
internal class InvalidRegistrationException : IocContainerException
/// <param name="message">The exception message</param>
public InvalidRegistrationException(string message)
: base(message)
{
/// <summary>
/// The registration is not valid
/// </summary>
/// <param name="message">The exception message</param>
public InvalidRegistrationException(string message)
: base(message)
{
}
}
}

@ -5,38 +5,37 @@
using System;
using System.Collections.Generic;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
public abstract class IocContainerException : Exception
{
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
public abstract class IocContainerException : Exception
{
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
protected IocContainerException() => InnerExceptions = new List<Exception>();
protected IocContainerException() => InnerExceptions = new List<Exception>();
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
/// <param name="message">The message of the <see cref="Exception"/></param>
protected IocContainerException(string message)
: base(message) =>
InnerExceptions = new List<Exception>();
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
/// <param name="message">The message of the <see cref="Exception"/></param>
protected IocContainerException(string message)
: base(message) =>
InnerExceptions = new List<Exception>();
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
/// <param name="message">The message of the <see cref="Exception"/></param>
/// <param name="innerException">The inner <see cref="Exception"/></param>
protected IocContainerException(string message, Exception innerException)
: base(message, innerException) =>
InnerExceptions = new List<Exception> {innerException};
/// <summary>
/// A base <see cref="Exception"/> for the <see cref="LightweightIocContainer"/>
/// </summary>
/// <param name="message">The message of the <see cref="Exception"/></param>
/// <param name="innerException">The inner <see cref="Exception"/></param>
protected IocContainerException(string message, Exception innerException)
: base(message, innerException) =>
InnerExceptions = new List<Exception> {innerException};
/// <summary>
/// The inner exceptions of the <see cref="IocContainerException"/>
/// </summary>
public List<Exception> InnerExceptions { get; protected init; }
}
/// <summary>
/// The inner exceptions of the <see cref="IocContainerException"/>
/// </summary>
public List<Exception> InnerExceptions { get; protected init; }
}

@ -5,24 +5,23 @@
using System;
using LightweightIocContainer.Interfaces;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The <see cref="System.Type"/> is already registered differently in this <see cref="IIocContainer"/>
/// </summary>
internal class MultipleRegistrationException : IocContainerException
{
/// <summary>
/// The <see cref="System.Type"/> is already registered differently in this <see cref="IIocContainer"/>
/// </summary>
internal class MultipleRegistrationException : IocContainerException
{
/// <summary>
/// The <see cref="System.Type"/> is already registered differently in this <see cref="IIocContainer"/>
/// </summary>
/// <param name="type">The <see cref="System.Type"/> that is already registered in this <see cref="IIocContainer"/></param>
public MultipleRegistrationException(Type type)
: base($"Type {type.Name} is already registered differently in this IocContainer.") =>
Type = type;
/// <param name="type">The <see cref="System.Type"/> that is already registered in this <see cref="IIocContainer"/></param>
public MultipleRegistrationException(Type type)
: base($"Type {type.Name} is already registered differently in this IocContainer.") =>
Type = type;
/// <summary>
/// The registered <see cref="System.Type"/>
/// </summary>
public Type Type { get; }
}
/// <summary>
/// The registered <see cref="System.Type"/>
/// </summary>
public Type Type { get; }
}

@ -4,25 +4,24 @@
using System;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// An error happened while trying to resolve a multiton
/// </summary>
internal class MultitonResolveException : InternalResolveException
{
/// <summary>
/// An error happened while trying to resolve a multiton
/// </summary>
internal class MultitonResolveException : InternalResolveException
{
/// <summary>
/// An error happened while trying to resolve a multiton
/// </summary>
/// <param name="message">The exception message</param>
/// <param name="type">The <see cref="System.Type"/> of the multiton that's responsible for the exception</param>
public MultitonResolveException(string message, Type type)
: base(message) =>
Type = type;
/// <param name="message">The exception message</param>
/// <param name="type">The <see cref="System.Type"/> of the multiton that's responsible for the exception</param>
public MultitonResolveException(string message, Type type)
: base(message) =>
Type = type;
/// <summary>
/// The <see cref="System.Type"/> of the multiton that's responsible for the exception
/// </summary>
public Type Type { get; }
}
/// <summary>
/// The <see cref="System.Type"/> of the multiton that's responsible for the exception
/// </summary>
public Type Type { get; }
}

@ -5,34 +5,33 @@
using System;
using System.Collections.Generic;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// No matching constructor was found for the given or resolvable arguments
/// </summary>
internal class NoMatchingConstructorFoundException : IocContainerException
{
/// <summary>
/// No matching constructor was found for the given or resolvable arguments
/// </summary>
internal class NoMatchingConstructorFoundException : IocContainerException
/// <param name="type">The <see cref="Type"/> with no matching constructor</param>
public NoMatchingConstructorFoundException(Type type)
: base($"No matching constructor for {type} found.")
{
/// <summary>
/// No matching constructor was found for the given or resolvable arguments
/// </summary>
/// <param name="type">The <see cref="Type"/> with no matching constructor</param>
public NoMatchingConstructorFoundException(Type type)
: base($"No matching constructor for {type} found.")
{
Type = type;
InnerExceptions = new List<Exception>();
}
Type = type;
InnerExceptions = new List<Exception>();
}
/// <summary>
/// The <see cref="Type"/> with no matching constructor
/// </summary>
public Type Type { get; }
/// <summary>
/// The <see cref="Type"/> with no matching constructor
/// </summary>
public Type Type { get; }
/// <summary>
/// Add an inner exception to the <see cref="IocContainerException.InnerExceptions"/>
/// </summary>
/// <param name="exception">The <see cref="ConstructorNotMatchingException"/></param>
public void AddInnerException(ConstructorNotMatchingException exception) => InnerExceptions.Add(exception);
}
/// <summary>
/// Add an inner exception to the <see cref="IocContainerException.InnerExceptions"/>
/// </summary>
/// <param name="exception">The <see cref="ConstructorNotMatchingException"/></param>
public void AddInnerException(ConstructorNotMatchingException exception) => InnerExceptions.Add(exception);
}

@ -4,24 +4,23 @@
using System;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// No public constructor can be found for a <see cref="Type"/>
/// </summary>
internal class NoPublicConstructorFoundException : IocContainerException
{
/// <summary>
/// No public constructor can be found for a <see cref="Type"/>
/// </summary>
internal class NoPublicConstructorFoundException : IocContainerException
{
/// <summary>
/// No public constructor can be found for a <see cref="Type"/>
/// </summary>
/// <param name="type">The <see cref="Type"/> with no public constructor</param>
public NoPublicConstructorFoundException(Type type)
: base($"No public constructor for {type} found.") =>
Type = type;
/// <param name="type">The <see cref="Type"/> with no public constructor</param>
public NoPublicConstructorFoundException(Type type)
: base($"No public constructor for {type} found.") =>
Type = type;
/// <summary>
/// The <see cref="Type"/> with no public constructor
/// </summary>
public Type Type { get; }
}
/// <summary>
/// The <see cref="Type"/> with no public constructor
/// </summary>
public Type Type { get; }
}

@ -5,24 +5,23 @@
using System;
using LightweightIocContainer.Interfaces;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// The <see cref="System.Type"/> is not registered in this <see cref="IIocContainer"/>
/// </summary>
internal class TypeNotRegisteredException : IocContainerException
{
/// <summary>
/// The <see cref="System.Type"/> is not registered in this <see cref="IIocContainer"/>
/// </summary>
internal class TypeNotRegisteredException : IocContainerException
{
/// <summary>
/// The <see cref="System.Type"/> is not registered in this <see cref="IIocContainer"/>
/// </summary>
/// <param name="type">The unregistered <see cref="System.Type"/></param>
public TypeNotRegisteredException(Type type)
: base($"Type {type.Name} is not registered in this IocContainer.") =>
Type = type;
/// <param name="type">The unregistered <see cref="System.Type"/></param>
public TypeNotRegisteredException(Type type)
: base($"Type {type.Name} is not registered in this IocContainer.") =>
Type = type;
/// <summary>
/// The unregistered <see cref="System.Type"/>
/// </summary>
public Type Type { get; }
}
/// <summary>
/// The unregistered <see cref="System.Type"/>
/// </summary>
public Type Type { get; }
}

@ -4,21 +4,20 @@
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Exceptions
namespace LightweightIocContainer.Exceptions;
/// <summary>
/// An unknown <see cref="IRegistration"/> was used
/// </summary>
internal class UnknownRegistrationException : IocContainerException
{
/// <summary>
/// An unknown <see cref="IRegistration"/> was used
/// </summary>
internal class UnknownRegistrationException : IocContainerException
/// <param name="message">The exception message</param>
public UnknownRegistrationException(string message)
: base(message)
{
/// <summary>
/// An unknown <see cref="IRegistration"/> was used
/// </summary>
/// <param name="message">The exception message</param>
public UnknownRegistrationException(string message)
: base(message)
{
}
}
}

@ -4,13 +4,12 @@
using LightweightIocContainer.Interfaces.Factories;
namespace LightweightIocContainer.Factories
namespace LightweightIocContainer.Factories;
/// <summary>
/// <see cref="ITypedFactory"/> implementation for custom implemented factories
/// </summary>
public class CustomTypedFactory<TFactory> : TypedFactoryBase<TFactory>
{
/// <summary>
/// <see cref="ITypedFactory"/> implementation for custom implemented factories
/// </summary>
public class CustomTypedFactory<TFactory> : TypedFactoryBase<TFactory>
{
}
}

@ -10,133 +10,132 @@ using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Factories;
namespace LightweightIocContainer.Factories
namespace LightweightIocContainer.Factories;
/// <summary>
/// Class to help implement an abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The type of the abstract factory</typeparam>
public class TypedFactory<TFactory> : TypedFactoryBase<TFactory>, ITypedFactory<TFactory>
{
private const string CLEAR_MULTITON_INSTANCE_METHOD_NAME = "ClearMultitonInstance";
/// <summary>
/// The
/// </summary>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public TypedFactory(IocContainer container) => Factory = CreateFactory(container);
/// <summary>
/// Class to help implement an abstract typed factory
/// The implemented abstract typed factory/>
/// </summary>
/// <typeparam name="TFactory">The type of the abstract factory</typeparam>
public class TypedFactory<TFactory> : TypedFactoryBase<TFactory>, ITypedFactory<TFactory>
public TFactory Factory { get; set; }
/// <summary>
/// Creates the factory from the given abstract factory type
/// </summary>
/// <exception cref="InvalidFactoryRegistrationException">Factory registration is invalid</exception>
/// <exception cref="IllegalAbstractMethodCreationException">Creation of abstract methods are illegal in their current state</exception>
private TFactory CreateFactory(IocContainer container)
{
private const string CLEAR_MULTITON_INSTANCE_METHOD_NAME = "ClearMultitonInstance";
/// <summary>
/// The
/// </summary>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public TypedFactory(IocContainer container) => Factory = CreateFactory(container);
/// <summary>
/// The implemented abstract typed factory/>
/// </summary>
public TFactory Factory { get; set; }
/// <summary>
/// Creates the factory from the given abstract factory type
/// </summary>
/// <exception cref="InvalidFactoryRegistrationException">Factory registration is invalid</exception>
/// <exception cref="IllegalAbstractMethodCreationException">Creation of abstract methods are illegal in their current state</exception>
private TFactory CreateFactory(IocContainer container)
{
Type factoryType = typeof(TFactory);
Type factoryType = typeof(TFactory);
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory");
TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{factoryType.Name}");
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory");
TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{factoryType.Name}");
typeBuilder.AddInterfaceImplementation(factoryType);
typeBuilder.AddInterfaceImplementation(factoryType);
//add `private readonly IIocContainer _container` field
FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IocContainer), FieldAttributes.Private | FieldAttributes.InitOnly);
//add `private readonly IIocContainer _container` field
FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IocContainer), FieldAttributes.Private | FieldAttributes.InitOnly);
//add ctor
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IocContainer)});
ILGenerator constructorGenerator = constructorBuilder.GetILGenerator();
constructorGenerator.Emit(OpCodes.Ldarg_0);
constructorGenerator.Emit(OpCodes.Ldarg_1);
constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field
constructorGenerator.Emit(OpCodes.Ret);
//add ctor
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IocContainer)});
ILGenerator constructorGenerator = constructorBuilder.GetILGenerator();
constructorGenerator.Emit(OpCodes.Ldarg_0);
constructorGenerator.Emit(OpCodes.Ldarg_1);
constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field
constructorGenerator.Emit(OpCodes.Ret);
foreach (MethodInfo createMethod in CreateMethods)
{
//create a method that looks like this
//public `createMethod.ReturnType` Create(`createMethod.GetParameters()`)
//{
// return IIocContainer.Resolve(`createMethod.ReturnType`, params);
//}
foreach (MethodInfo createMethod in CreateMethods)
{
//create a method that looks like this
//public `createMethod.ReturnType` Create(`createMethod.GetParameters()`)
//{
// return IIocContainer.Resolve(`createMethod.ReturnType`, params);
//}
ParameterInfo[] args = createMethod.GetParameters();
ParameterInfo[] args = createMethod.GetParameters();
MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray());
typeBuilder.DefineMethodOverride(methodBuilder, createMethod);
MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray());
typeBuilder.DefineMethodOverride(methodBuilder, createMethod);
ILGenerator generator = methodBuilder.GetILGenerator();
ILGenerator generator = methodBuilder.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, containerFieldBuilder);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, containerFieldBuilder);
if (args.Any())
{
generator.Emit(OpCodes.Ldc_I4_S, args.Length);
generator.Emit(OpCodes.Newarr, typeof(object));
for (int i = 0; i < args.Length; i++)
{
generator.Emit(OpCodes.Dup);
generator.Emit(OpCodes.Ldc_I4_S, i);
generator.Emit(OpCodes.Ldarg_S, i + 1);
generator.Emit(OpCodes.Box, args[i].ParameterType); //Boxing is only needed for simple datatypes, but for now it is not a problem to box everything
generator.Emit(OpCodes.Stelem_Ref);
}
}
else
if (args.Any())
{
generator.Emit(OpCodes.Ldc_I4_S, args.Length);
generator.Emit(OpCodes.Newarr, typeof(object));
for (int i = 0; i < args.Length; i++)
{
MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))!.MakeGenericMethod(typeof(object));
generator.EmitCall(OpCodes.Call, emptyArray, null);
generator.Emit(OpCodes.Dup);
generator.Emit(OpCodes.Ldc_I4_S, i);
generator.Emit(OpCodes.Ldarg_S, i + 1);
generator.Emit(OpCodes.Box, args[i].ParameterType); //Boxing is only needed for simple datatypes, but for now it is not a problem to box everything
generator.Emit(OpCodes.Stelem_Ref);
}
generator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.FactoryResolve), new[] { typeof(object[]) })!.MakeGenericMethod(createMethod.ReturnType), null);
generator.Emit(OpCodes.Castclass, createMethod.ReturnType);
generator.Emit(OpCodes.Ret);
}
//if factory contains a method to clear multiton instances
MethodInfo? multitonClearMethod = factoryType.GetMethods().FirstOrDefault(m => m.Name.Equals(CLEAR_MULTITON_INSTANCE_METHOD_NAME));
if (multitonClearMethod != null)
else
{
//create a method that looks like this
//public void ClearMultitonInstance<typeToClear>()
//{
// IIocContainer.ClearMultitonInstances<typeToClear>();
//}
MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))!.MakeGenericMethod(typeof(object));
generator.EmitCall(OpCodes.Call, emptyArray, null);
}
if (multitonClearMethod.IsGenericMethod)
{
Type? typeToClear = multitonClearMethod.GetGenericArguments().FirstOrDefault();
if (typeToClear == null)
throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod);
generator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.FactoryResolve), new[] { typeof(object[]) })!.MakeGenericMethod(createMethod.ReturnType), null);
generator.Emit(OpCodes.Castclass, createMethod.ReturnType);
generator.Emit(OpCodes.Ret);
}
MethodBuilder multitonClearMethodBuilder = typeBuilder.DefineMethod(multitonClearMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
multitonClearMethod.ReturnType, null);
multitonClearMethodBuilder.DefineGenericParameters(typeToClear.Name);
//if factory contains a method to clear multiton instances
MethodInfo? multitonClearMethod = factoryType.GetMethods().FirstOrDefault(m => m.Name.Equals(CLEAR_MULTITON_INSTANCE_METHOD_NAME));
if (multitonClearMethod != null)
{
//create a method that looks like this
//public void ClearMultitonInstance<typeToClear>()
//{
// IIocContainer.ClearMultitonInstances<typeToClear>();
//}
typeBuilder.DefineMethodOverride(multitonClearMethodBuilder, multitonClearMethod);
if (multitonClearMethod.IsGenericMethod)
{
Type? typeToClear = multitonClearMethod.GetGenericArguments().FirstOrDefault();
if (typeToClear == null)
throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod);
ILGenerator multitonClearGenerator = multitonClearMethodBuilder.GetILGenerator();
multitonClearGenerator.Emit(OpCodes.Ldarg_0);
multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder);
MethodBuilder multitonClearMethodBuilder = typeBuilder.DefineMethod(multitonClearMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
multitonClearMethod.ReturnType, null);
multitonClearMethodBuilder.DefineGenericParameters(typeToClear.Name);
multitonClearGenerator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.ClearMultitonInstances))!.MakeGenericMethod(typeToClear), null);
multitonClearGenerator.Emit(OpCodes.Ret);
}
else
{
throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod);
}
}
typeBuilder.DefineMethodOverride(multitonClearMethodBuilder, multitonClearMethod);
ILGenerator multitonClearGenerator = multitonClearMethodBuilder.GetILGenerator();
multitonClearGenerator.Emit(OpCodes.Ldarg_0);
multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder);
return Creator.CreateInstance<TFactory>(typeBuilder.CreateTypeInfo()!.AsType(), container);
multitonClearGenerator.EmitCall(OpCodes.Call, typeof(IocContainer).GetMethod(nameof(IocContainer.ClearMultitonInstances))!.MakeGenericMethod(typeToClear), null);
multitonClearGenerator.Emit(OpCodes.Ret);
}
else
{
throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod);
}
}
return Creator.CreateInstance<TFactory>(typeBuilder.CreateTypeInfo()!.AsType(), container);
}
}

@ -9,28 +9,27 @@ using System.Reflection;
using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces.Factories;
namespace LightweightIocContainer.Factories
namespace LightweightIocContainer.Factories;
/// <summary>
/// Base class for the <see cref="ITypedFactory"/>
/// </summary>
public abstract class TypedFactoryBase<TFactory> : ITypedFactory
{
/// <summary>
/// Base class for the <see cref="ITypedFactory"/>
/// The create methods of this <see cref="ITypedFactory"/>
/// </summary>
public abstract class TypedFactoryBase<TFactory> : ITypedFactory
public List<MethodInfo> CreateMethods
{
/// <summary>
/// The create methods of this <see cref="ITypedFactory"/>
/// </summary>
public List<MethodInfo> CreateMethods
get
{
get
{
Type factoryType = typeof(TFactory);
Type factoryType = typeof(TFactory);
List<MethodInfo> createMethods = factoryType.GetMethods().Where(m => m.ReturnType != typeof(void)).ToList();
if (!createMethods.Any())
throw new InvalidFactoryRegistrationException($"Factory {factoryType.Name} has no create methods.");
List<MethodInfo> createMethods = factoryType.GetMethods().Where(m => m.ReturnType != typeof(void)).ToList();
if (!createMethods.Any())
throw new InvalidFactoryRegistrationException($"Factory {factoryType.Name} has no create methods.");
return createMethods;
}
return createMethods;
}
}
}

@ -6,53 +6,52 @@ using System;
using System.Reflection;
using LightweightIocContainer.Exceptions;
namespace LightweightIocContainer
namespace LightweightIocContainer;
/// <summary>
/// Helper class to call a generic method without generic type parameters
/// </summary>
internal static class GenericMethodCaller
{
/// <summary>
/// Helper class to call a generic method without generic type parameters
/// Call a generic method without generic type parameters
/// </summary>
internal static class GenericMethodCaller
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object? Call(object caller, string functionName, Type genericParameter, BindingFlags bindingFlags, params object?[] parameters)
{
/// <summary>
/// Call a generic method without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="bindingFlags">The <see cref="BindingFlags"/> to find the method</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object? Call(object caller, string functionName, Type genericParameter, BindingFlags bindingFlags, params object?[] parameters)
{
MethodInfo? method = caller.GetType().GetMethod(functionName, bindingFlags);
MethodInfo? genericMethod = method?.MakeGenericMethod(genericParameter);
MethodInfo? method = caller.GetType().GetMethod(functionName, bindingFlags);
MethodInfo? genericMethod = method?.MakeGenericMethod(genericParameter);
if (genericMethod == null)
throw new GenericMethodNotFoundException(functionName);
if (genericMethod == null)
throw new GenericMethodNotFoundException(functionName);
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()`
{
return genericMethod.Invoke(caller, parameters);
}
catch (Exception ex)
{
throw ex.GetBaseException();
}
try //exceptions thrown by methods called with invoke are wrapped into another exception, the exception thrown by the invoked method can be returned by `Exception.GetBaseException()`
{
return genericMethod.Invoke(caller, parameters);
}
catch (Exception ex)
{
throw ex.GetBaseException();
}
/// <summary>
/// Call a private generic method without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object? CallPrivate(object caller, string functionName, Type genericParameter, params object?[] parameters) =>
Call(caller, functionName, genericParameter, BindingFlags.NonPublic | BindingFlags.Instance, parameters);
}
/// <summary>
/// Call a private generic method without generic type parameters
/// </summary>
/// <param name="caller">The caller of the method</param>
/// <param name="functionName">The name of the method to call</param>
/// <param name="genericParameter">The generic parameter as <see cref="Type"/> parameter</param>
/// <param name="parameters">The parameters of the method</param>
/// <returns>The result of invoking the method</returns>
/// <exception cref="GenericMethodNotFoundException">Could not find the generic method</exception>
/// <exception cref="Exception">Any <see cref="Exception"/> thrown after invoking the generic method</exception>
public static object? CallPrivate(object caller, string functionName, Type genericParameter, params object?[] parameters) =>
Call(caller, functionName, genericParameter, BindingFlags.NonPublic | BindingFlags.Instance, parameters);
}

@ -9,44 +9,43 @@ using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Installers
namespace LightweightIocContainer.Installers;
/// <summary>
/// An <see cref="IIocInstaller"/> that installs all <see cref="IIocInstaller"/>s for its given <see cref="Assembly"/>
/// </summary>
public class AssemblyInstaller : IAssemblyInstaller
{
/// <summary>
/// An <see cref="IIocInstaller"/> that installs all <see cref="IIocInstaller"/>s for its given <see cref="Assembly"/>
/// </summary>
public class AssemblyInstaller : IAssemblyInstaller
/// <param name="assembly">The <see cref="Assembly"/> from where the <see cref="IIocInstaller"/>s will be installed</param>
public AssemblyInstaller(Assembly assembly)
{
/// <summary>
/// An <see cref="IIocInstaller"/> that installs all <see cref="IIocInstaller"/>s for its given <see cref="Assembly"/>
/// </summary>
/// <param name="assembly">The <see cref="Assembly"/> from where the <see cref="IIocInstaller"/>s will be installed</param>
public AssemblyInstaller(Assembly assembly)
{
Installers = new List<IIocInstaller>();
Installers = new List<IIocInstaller>();
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (!typeof(IIocInstaller).IsAssignableFrom(type) || type.IsNestedPrivate)
continue;
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (!typeof(IIocInstaller).IsAssignableFrom(type) || type.IsNestedPrivate)
continue;
Installers.Add(Creator.CreateInstance<IIocInstaller>(type));
}
Installers.Add(Creator.CreateInstance<IIocInstaller>(type));
}
}
/// <summary>
/// The <see cref="IIocInstaller"/>s of the Assembly that this <see cref="AssemblyInstaller"/> is installing
/// </summary>
public List<IIocInstaller> Installers { get; }
/// <summary>
/// The <see cref="IIocInstaller"/>s of the Assembly that this <see cref="AssemblyInstaller"/> is installing
/// </summary>
public List<IIocInstaller> Installers { get; }
/// <summary>
/// Install the found <see cref="IIocInstaller"/>s in the given <see cref="IIocContainer"/>
/// </summary>
/// <param name="registration">The <see cref="IRegistrationCollector"/> where <see cref="IRegistration"/>s are added</param>
public void Install(IRegistrationCollector registration)
{
foreach (IIocInstaller installer in Installers)
installer.Install(registration);
}
/// <summary>
/// Install the found <see cref="IIocInstaller"/>s in the given <see cref="IIocContainer"/>
/// </summary>
/// <param name="registration">The <see cref="IRegistrationCollector"/> where <see cref="IRegistration"/>s are added</param>
public void Install(IRegistrationCollector registration)
{
foreach (IIocInstaller installer in Installers)
installer.Install(registration);
}
}

@ -5,28 +5,27 @@
using System.Reflection;
using LightweightIocContainer.Interfaces.Installers;
namespace LightweightIocContainer.Installers
namespace LightweightIocContainer.Installers;
/// <summary>
/// Helper class that supplies methods to find the wanted <see cref="Assembly"/>
/// </summary>
public static class FromAssembly
{
/// <summary>
/// Helper class that supplies methods to find the wanted <see cref="Assembly"/>
/// Get an <see cref="IAssemblyInstaller"/> that installs from the <see cref="Assembly"/> calling the method
/// </summary>
public static class FromAssembly
/// <returns>A new <see cref="IAssemblyInstaller"/> with the calling <see cref="Assembly"/></returns>
public static IAssemblyInstaller This()
{
/// <summary>
/// Get an <see cref="IAssemblyInstaller"/> that installs from the <see cref="Assembly"/> calling the method
/// </summary>
/// <returns>A new <see cref="IAssemblyInstaller"/> with the calling <see cref="Assembly"/></returns>
public static IAssemblyInstaller This()
{
Assembly assembly = Assembly.GetCallingAssembly();
return new AssemblyInstaller(assembly);
}
/// <summary>
/// Get an <see cref="IAssemblyInstaller"/> that installs from the given <see cref="Assembly"/>
/// </summary>
/// <param name="assembly">The given <see cref="Assembly"/></param>
/// <returns>A new <see cref="IAssemblyInstaller"/> with the given <see cref="Assembly"/></returns>
public static IAssemblyInstaller Instance(Assembly assembly) => new AssemblyInstaller(assembly);
Assembly assembly = Assembly.GetCallingAssembly();
return new AssemblyInstaller(assembly);
}
/// <summary>
/// Get an <see cref="IAssemblyInstaller"/> that installs from the given <see cref="Assembly"/>
/// </summary>
/// <param name="assembly">The given <see cref="Assembly"/></param>
/// <returns>A new <see cref="IAssemblyInstaller"/> with the given <see cref="Assembly"/></returns>
public static IAssemblyInstaller Instance(Assembly assembly) => new AssemblyInstaller(assembly);
}

@ -5,28 +5,27 @@
using System.Collections.Generic;
using System.Reflection;
namespace LightweightIocContainer.Interfaces.Factories
namespace LightweightIocContainer.Interfaces.Factories;
/// <summary>
/// Non-generic <see cref="ITypedFactory{TFactory}"/>
/// </summary>
public interface ITypedFactory
{
/// <summary>
/// Non-generic <see cref="ITypedFactory{TFactory}"/>
/// The create methods of this <see cref="ITypedFactory"/>
/// </summary>
public interface ITypedFactory
{
/// <summary>
/// The create methods of this <see cref="ITypedFactory"/>
/// </summary>
List<MethodInfo> CreateMethods { get; }
}
List<MethodInfo> CreateMethods { get; }
}
/// <summary>
/// Class to help implement an abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The type of the abstract factory</typeparam>
public interface ITypedFactory<TFactory> : ITypedFactory
{
/// <summary>
/// Class to help implement an abstract typed factory
/// The implemented abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The type of the abstract factory</typeparam>
public interface ITypedFactory<TFactory> : ITypedFactory
{
/// <summary>
/// The implemented abstract typed factory
/// </summary>
TFactory Factory { get; set; }
}
TFactory Factory { get; set; }
}

@ -6,37 +6,36 @@ using System;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Interfaces
namespace LightweightIocContainer.Interfaces;
/// <summary>
/// The main container that carries all <see cref="IRegistration"/>s
/// </summary>
public interface IIocContainer : IDisposable
{
/// <summary>
/// The main container that carries all <see cref="IRegistration"/>s
/// Install the given installers for the current <see cref="IIocContainer"/>
/// </summary>
public interface IIocContainer : IDisposable
{
/// <summary>
/// Install the given installers for the current <see cref="IIocContainer"/>
/// </summary>
/// <param name="installers">The given <see cref="IIocInstaller"/>s</param>
/// <returns>An instance of the current <see cref="IIocContainer"/></returns>
IIocContainer Install(params IIocInstaller[] installers);
/// <param name="installers">The given <see cref="IIocInstaller"/>s</param>
/// <returns>An instance of the current <see cref="IIocContainer"/></returns>
IIocContainer Install(params IIocInstaller[] installers);
/// <summary>
/// Register an <see cref="IRegistration"/> at this <see cref="IocContainer"/>
/// </summary>
/// <param name="addRegistration">The <see cref="Func{T, TResult}"/> that creates an <see cref="IRegistration"/></param>
public void Register(Func<IRegistrationCollector, IRegistration> addRegistration);
/// <summary>
/// Register an <see cref="IRegistration"/> at this <see cref="IocContainer"/>
/// </summary>
/// <param name="addRegistration">The <see cref="Func{T, TResult}"/> that creates an <see cref="IRegistration"/></param>
public void Register(Func<IRegistrationCollector, IRegistration> addRegistration);
/// <summary>
/// Clear the multiton instances of the given <see cref="Type"/> from the registered multitons list
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> to clear the multiton instances</typeparam>
void ClearMultitonInstances<T>();
/// <summary>
/// Clear the multiton instances of the given <see cref="Type"/> from the registered multitons list
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> to clear the multiton instances</typeparam>
void ClearMultitonInstances<T>();
/// <summary>
/// Is the given <see cref="Type"/> registered with this <see cref="IIocContainer"/>
/// </summary>
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <returns>True if the given <see cref="Type"/> is registered with this <see cref="IIocContainer"/>, false if not</returns>
bool IsTypeRegistered<T>();
}
/// <summary>
/// Is the given <see cref="Type"/> registered with this <see cref="IIocContainer"/>
/// </summary>
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <returns>True if the given <see cref="Type"/> is registered with this <see cref="IIocContainer"/>, false if not</returns>
bool IsTypeRegistered<T>();
}

@ -4,26 +4,25 @@
using System;
namespace LightweightIocContainer.Interfaces
namespace LightweightIocContainer.Interfaces;
/// <summary>
/// Provides <see cref="Resolve{T}()"/> methods
/// </summary>
public interface IIocResolver : IDisposable
{
/// <summary>
/// Provides <see cref="Resolve{T}()"/> methods
/// Gets an instance of the given <see cref="Type"/>
/// </summary>
public interface IIocResolver : IDisposable
{
/// <summary>
/// Gets an instance of the given <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <returns>An instance of the given <see cref="Type"/></returns>
T Resolve<T>();
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <returns>An instance of the given <see cref="Type"/></returns>
T Resolve<T>();
/// <summary>
/// Gets an instance of the given <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <param name="arguments">The constructor arguments</param>
/// <returns>An instance of the given <see cref="Type"/></returns>
T Resolve<T>(params object[] arguments);
}
/// <summary>
/// Gets an instance of the given <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The given <see cref="Type"/></typeparam>
/// <param name="arguments">The constructor arguments</param>
/// <returns>An instance of the given <see cref="Type"/></returns>
T Resolve<T>(params object[] arguments);
}

@ -5,16 +5,15 @@
using System.Collections.Generic;
using System.Reflection;
namespace LightweightIocContainer.Interfaces.Installers
namespace LightweightIocContainer.Interfaces.Installers;
/// <summary>
/// An <see cref="IIocInstaller"/> that installs all <see cref="IIocInstaller"/>s for its given <see cref="Assembly"/>
/// </summary>
public interface IAssemblyInstaller : IIocInstaller
{
/// <summary>
/// An <see cref="IIocInstaller"/> that installs all <see cref="IIocInstaller"/>s for its given <see cref="Assembly"/>
/// The <see cref="IIocInstaller"/>s of the <see cref="Assembly"/> that this <see cref="IAssemblyInstaller"/> is installing
/// </summary>
public interface IAssemblyInstaller : IIocInstaller
{
/// <summary>
/// The <see cref="IIocInstaller"/>s of the <see cref="Assembly"/> that this <see cref="IAssemblyInstaller"/> is installing
/// </summary>
List<IIocInstaller> Installers { get; }
}
List<IIocInstaller> Installers { get; }
}

@ -4,17 +4,16 @@
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Interfaces.Installers
namespace LightweightIocContainer.Interfaces.Installers;
/// <summary>
/// The base class for <see cref="IIocContainer"/> installers
/// </summary>
public interface IIocInstaller
{
/// <summary>
/// The base class for <see cref="IIocContainer"/> installers
/// Install the needed <see cref="IRegistration"/>s in the given <see cref="IIocContainer"/>
/// </summary>
public interface IIocInstaller
{
/// <summary>
/// Install the needed <see cref="IRegistration"/>s in the given <see cref="IIocContainer"/>
/// </summary>
/// <param name="registration">The <see cref="IRegistrationCollector"/> where <see cref="IRegistration"/>s are added</param>
void Install(IRegistrationCollector registration);
}
/// <param name="registration">The <see cref="IRegistrationCollector"/> where <see cref="IRegistration"/>s are added</param>
void Install(IRegistrationCollector registration);
}

@ -5,32 +5,31 @@
using System;
using LightweightIocContainer.Interfaces.Installers;
namespace LightweightIocContainer.Interfaces.Registrations.Fluent
namespace LightweightIocContainer.Interfaces.Registrations.Fluent;
/// <summary>
/// Provides an <see cref="OnCreateAction"/> to the generic <see cref="IOnCreate{TInterface, TImplementation}"/>
/// </summary>
public interface IOnCreate
{
/// <summary>
/// Provides an <see cref="OnCreateAction"/> to the generic <see cref="IOnCreate{TInterface, TImplementation}"/>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface, TImplementation}.OnCreate"/></para>
/// </summary>
public interface IOnCreate
{
/// <summary>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface, TImplementation}.OnCreate"/></para>
/// </summary>
internal Action<object?>? OnCreateAction { get; }
}
internal Action<object?>? OnCreateAction { get; }
}
/// <summary>
/// Provides an <see cref="OnCreate"/> method to an <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
public interface IOnCreate<TInterface, TImplementation> : IOnCreate where TImplementation : TInterface
{
/// <summary>
/// Provides an <see cref="OnCreate"/> method to an <see cref="IRegistrationBase"/>
/// Pass an <see cref="Action{T}"/> that will be invoked when an instance of this type is created
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
public interface IOnCreate<TInterface, TImplementation> : IOnCreate where TImplementation : TInterface
{
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
ITypedRegistration<TInterface, TImplementation> OnCreate(Action<TImplementation?> action);
}
/// <param name="action">The <see cref="Action{T}"/></param>
/// <returns>The current instance of this <see cref="ITypedRegistration{TInterface,TImplementation}"/></returns>
ITypedRegistration<TInterface, TImplementation> OnCreate(Action<TImplementation?> action);
}

@ -4,34 +4,33 @@
using LightweightIocContainer.Interfaces.Factories;
namespace LightweightIocContainer.Interfaces.Registrations.Fluent
namespace LightweightIocContainer.Interfaces.Registrations.Fluent;
/// <summary>
/// Provides a <see cref="WithFactory{TFactory}"/> method to an <see cref="IRegistrationBase"/>
/// </summary>
public interface IWithFactory
{
/// <summary>
/// Provides a <see cref="WithFactory{TFactory}"/> method to an <see cref="IRegistrationBase"/>
/// Register an abstract typed factory for the <see cref="IRegistrationBase"/>
/// </summary>
public interface IWithFactory
{
/// <summary>
/// Register an abstract typed factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
IRegistrationBase WithFactory<TFactory>();
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
IRegistrationBase WithFactory<TFactory>();
/// <summary>
/// Register a custom implemented factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactoryInterface">The type of the interface for the custom factory</typeparam>
/// <typeparam name="TFactoryImplementation">The type of the implementation for the custom factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
IRegistrationBase WithFactory<TFactoryInterface, TFactoryImplementation>() where TFactoryImplementation : TFactoryInterface;
}
/// <summary>
/// Register a custom implemented factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactoryInterface">The type of the interface for the custom factory</typeparam>
/// <typeparam name="TFactoryImplementation">The type of the implementation for the custom factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
IRegistrationBase WithFactory<TFactoryInterface, TFactoryImplementation>() where TFactoryImplementation : TFactoryInterface;
}
internal interface IWithFactoryInternal : IWithFactory
{
/// <summary>
/// The Factory added with the <see cref="IWithFactory.WithFactory{TFactory}"/> method
/// </summary>
ITypedFactory? Factory { get; }
}
internal interface IWithFactoryInternal : IWithFactory
{
/// <summary>
/// The Factory added with the <see cref="IWithFactory.WithFactory{TFactory}"/> method
/// </summary>
ITypedFactory? Factory { get; }
}

@ -6,38 +6,37 @@ using System;
using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces.Installers;
namespace LightweightIocContainer.Interfaces.Registrations.Fluent
namespace LightweightIocContainer.Interfaces.Registrations.Fluent;
/// <summary>
/// Provides a <see cref="WithParameters(object[])"/> method to an <see cref="IRegistration"/>
/// </summary>
public interface IWithParameters
{
/// <summary>
/// Provides a <see cref="WithParameters(object[])"/> method to an <see cref="IRegistration"/>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving</para>
/// </summary>
public interface IWithParameters
{
/// <summary>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters</param>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="IWithParametersInternal.Parameters"/> are already set or no parameters given</exception>
IRegistrationBase WithParameters(params object[] parameters);
/// <param name="parameters">The parameters</param>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="IWithParametersInternal.Parameters"/> are already set or no parameters given</exception>
IRegistrationBase WithParameters(params object[] parameters);
/// <summary>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters with their position</param>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="IWithParametersInternal.Parameters"/> are already set or no parameters given</exception>
IRegistrationBase WithParameters(params (int index, object parameter)[] parameters);
}
/// <summary>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters with their position</param>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="IWithParametersInternal.Parameters"/> are already set or no parameters given</exception>
IRegistrationBase WithParameters(params (int index, object parameter)[] parameters);
}
internal interface IWithParametersInternal : IWithParameters
{
/// <summary>
/// An <see cref="Array"/> of parameters that are used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IWithParameters.WithParameters(object[])"/></para>
/// </summary>
object[]? Parameters { get; }
}
internal interface IWithParametersInternal : IWithParameters
{
/// <summary>
/// An <see cref="Array"/> of parameters that are used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IWithParameters.WithParameters(object[])"/></para>
/// </summary>
object[]? Parameters { get; }
}

@ -2,16 +2,15 @@
// // Created: 2020-01-29
// // Copyright(c) 2020 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// Provides a <see cref="LightweightIocContainer.Lifestyle"/> to an <see cref="IRegistration"/>
/// </summary>
public interface ILifestyleProvider
{
/// <summary>
/// Provides a <see cref="LightweightIocContainer.Lifestyle"/> to an <see cref="IRegistration"/>
/// The Lifestyle of Instances that are created with this <see cref="IRegistration"/>
/// </summary>
public interface ILifestyleProvider
{
/// <summary>
/// The Lifestyle of Instances that are created with this <see cref="IRegistration"/>
/// </summary>
Lifestyle Lifestyle { get; }
}
Lifestyle Lifestyle { get; }
}

@ -2,16 +2,15 @@
// Created: 2020-11-19
// Copyright(c) 2020 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// An <see cref="IRegistration"/> 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
{
/// <summary>
/// An <see cref="IRegistration"/> 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
{
}
}

@ -4,68 +4,67 @@
using System.Collections.Generic;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// The base interface for every <see cref="IMultipleRegistration{TInterface1,TInterface2,TImplementation}"/> to register multiple interfaces
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TImplementation> : ITypedRegistration<TInterface1, TImplementation> where TImplementation : TInterface1
{
/// <summary>
/// The base interface for every <see cref="IMultipleRegistration{TInterface1,TInterface2,TImplementation}"/> to register multiple interfaces
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="IMultipleRegistration{TInterface1,TImplementation}"/>
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TImplementation> : ITypedRegistration<TInterface1, TImplementation> where TImplementation : TInterface1
{
/// <summary>
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="IMultipleRegistration{TInterface1,TImplementation}"/>
/// </summary>
List<IRegistration> Registrations { get; }
}
List<IRegistration> Registrations { get; }
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2
{
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3
{
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4
{
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TInterface5">The fifth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4, TInterface5
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TInterface5">The fifth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
public interface IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> : IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4, TInterface5
{
}
}

@ -4,26 +4,25 @@
using System;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// Non generic <see cref="IMultipleRegistration{TInterface1,TImplementation}"/>
/// </summary>
public interface IMultitonRegistration : ITypedRegistration
{
/// <summary>
/// Non generic <see cref="IMultipleRegistration{TInterface1,TImplementation}"/>
/// The <see cref="Type"/> of the multiton scope
/// </summary>
public interface IMultitonRegistration : ITypedRegistration
{
/// <summary>
/// The <see cref="Type"/> of the multiton scope
/// </summary>
Type Scope { get; }
}
Type Scope { get; }
}
/// <summary>
/// The registration that is used to register a multiton
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
public interface IMultitonRegistration<TInterface, TImplementation> : IMultitonRegistration, ITypedRegistration<TInterface, TImplementation> where TImplementation : TInterface
{
/// <summary>
/// The registration that is used to register a multiton
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
public interface IMultitonRegistration<TInterface, TImplementation> : IMultitonRegistration, ITypedRegistration<TInterface, TImplementation> where TImplementation : TInterface
{
}
}

@ -2,13 +2,12 @@
// Created: 2020-09-18
// Copyright(c) 2020 SimonG. All Rights Reserved.
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// <see cref="IRegistration"/> for open generic types
/// </summary>
public interface IOpenGenericRegistration : ITypedRegistration
{
/// <summary>
/// <see cref="IRegistration"/> for open generic types
/// </summary>
public interface IOpenGenericRegistration : ITypedRegistration
{
}
}

@ -4,16 +4,15 @@
using System;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// The base registration that is used to register an Interface
/// </summary>
public interface IRegistration
{
/// <summary>
/// The base registration that is used to register an Interface
/// The <see cref="Type"/> of the Interface that is registered with this <see cref="IRegistration"/>
/// </summary>
public interface IRegistration
{
/// <summary>
/// The <see cref="Type"/> of the Interface that is registered with this <see cref="IRegistration"/>
/// </summary>
Type InterfaceType { get; }
}
Type InterfaceType { get; }
}

@ -4,13 +4,12 @@
using LightweightIocContainer.Interfaces.Registrations.Fluent;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// The <see cref="IRegistrationBase"/> that is used to register an Interface and extends the <see cref="IRegistration"/> with fluent options
/// </summary>
public interface IRegistrationBase : IRegistration, IWithFactory, IWithParameters, IWithDisposeStrategy
{
/// <summary>
/// The <see cref="IRegistrationBase"/> that is used to register an Interface and extends the <see cref="IRegistration"/> with fluent options
/// </summary>
public interface IRegistrationBase : IRegistration, IWithFactory, IWithParameters, IWithDisposeStrategy
{
}
}

@ -4,24 +4,23 @@
using System;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// The <see cref="IRegistration"/> to register either only an interface or only a <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the <see cref="IRegistration"/></typeparam>
public interface ISingleTypeRegistration<T> : IRegistrationBase
{
/// <summary>
/// The <see cref="IRegistration"/> to register either only an interface or only a <see cref="Type"/>
/// <see cref="Func{T,TResult}"/> that is invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the <see cref="IRegistration"/></typeparam>
public interface ISingleTypeRegistration<T> : IRegistrationBase
{
/// <summary>
/// <see cref="Func{T,TResult}"/> that is invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
Func<IIocResolver, T>? FactoryMethod { get; }
Func<IIocResolver, T>? FactoryMethod { get; }
/// <summary>
/// Pass a <see cref="Func{T,TResult}"/> that will be invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
/// <param name="factoryMethod">The <see cref="Func{T,TResult}"/></param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
ISingleTypeRegistration<T> WithFactoryMethod(Func<IIocResolver, T> factoryMethod);
}
/// <summary>
/// Pass a <see cref="Func{T,TResult}"/> that will be invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
/// <param name="factoryMethod">The <see cref="Func{T,TResult}"/></param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
ISingleTypeRegistration<T> WithFactoryMethod(Func<IIocResolver, T> factoryMethod);
}

@ -4,17 +4,16 @@
using LightweightIocContainer.Interfaces.Factories;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// The registration that is used to register an abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
public interface ITypedFactoryRegistration<TFactory> : IRegistration
{
/// <summary>
/// The registration that is used to register an abstract typed factory
/// The class that contains the implemented abstract factory of this <see cref="ITypedFactoryRegistration{TFactory}"/>
/// </summary>
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
public interface ITypedFactoryRegistration<TFactory> : IRegistration
{
/// <summary>
/// The class that contains the implemented abstract factory of this <see cref="ITypedFactoryRegistration{TFactory}"/>
/// </summary>
ITypedFactory<TFactory> Factory { get; }
}
ITypedFactory<TFactory> Factory { get; }
}

@ -5,24 +5,23 @@
using System;
using LightweightIocContainer.Interfaces.Registrations.Fluent;
namespace LightweightIocContainer.Interfaces.Registrations
namespace LightweightIocContainer.Interfaces.Registrations;
/// <summary>
/// A base <see cref="ITypedRegistration"/> without generic interface and implementation
/// </summary>
public interface ITypedRegistration : IRegistrationBase
{
/// <summary>
/// A base <see cref="ITypedRegistration"/> without generic interface and implementation
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IRegistration"/>
/// </summary>
public interface ITypedRegistration : IRegistrationBase
{
/// <summary>
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IRegistration"/>
/// </summary>
Type ImplementationType { get; }
}
Type ImplementationType { get; }
}
/// <summary>
/// A <see cref="IRegistration"/> that implements a <see cref="Type"/>
/// </summary>
public interface ITypedRegistration<TInterface, TImplementation> : ITypedRegistration, IOnCreate<TInterface, TImplementation> where TImplementation : TInterface
{
/// <summary>
/// A <see cref="IRegistration"/> that implements a <see cref="Type"/>
/// </summary>
public interface ITypedRegistration<TInterface, TImplementation> : ITypedRegistration, IOnCreate<TInterface, TImplementation> where TImplementation : TInterface
{
}
}

File diff suppressed because it is too large Load Diff

@ -4,26 +4,25 @@
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer
namespace LightweightIocContainer;
/// <summary>
/// The Lifestyles that can be used for a <see cref="IRegistrationBase"/>
/// </summary>
public enum Lifestyle
{
/// <summary>
/// The Lifestyles that can be used for a <see cref="IRegistrationBase"/>
/// A new instance gets created every time an instance is resolved
/// </summary>
public enum Lifestyle
{
/// <summary>
/// A new instance gets created every time an instance is resolved
/// </summary>
Transient,
Transient,
/// <summary>
/// One instance is created that gets returned every time an instance is resolved
/// </summary>
Singleton,
/// <summary>
/// One instance is created that gets returned every time an instance is resolved
/// </summary>
Singleton,
/// <summary>
/// A new instance gets created if the given scope has no created instance yet. Otherwise the already created instance is used.
/// </summary>
Multiton
}
/// <summary>
/// A new instance gets created if the given scope has no created instance yet. Otherwise the already created instance is used.
/// </summary>
Multiton
}

@ -7,55 +7,54 @@ using System.Collections.Generic;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// An <see cref="IRegistrationBase"/> 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>
internal class MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> : MultitonRegistration<TInterface1, TImplementation>, IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
{
/// <summary>
/// An <see cref="IRegistrationBase"/> 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>
internal class MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> : MultitonRegistration<TInterface1, TImplementation>, IMultipleMultitonRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
/// <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>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope, IocContainer container)
: base(interfaceType1, implementationType, scope, container)
{
/// <summary>
/// An <see cref="IRegistrationBase"/> 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>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope, IocContainer container)
: base(interfaceType1, implementationType, scope, container)
Registrations = new List<IRegistration>
{
Registrations = new List<IRegistration>
{
new MultitonRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, scope, container),
new MultitonRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, scope, container)
};
}
new MultitonRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, scope, container),
new MultitonRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, scope, container)
};
}
/// <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>
/// 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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
{
foreach (IRegistration registration in Registrations)
{
foreach (IRegistration 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;
if (registration is IMultitonRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is IMultitonRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}

@ -7,239 +7,238 @@ using System.Collections.Generic;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// The base class for every <see cref="IMultipleRegistration{TInterface1,TInterface2, TImplementation}"/> to register multiple interfaces
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal abstract class MultipleRegistration<TInterface1, TImplementation> : TypedRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1
{
/// <summary>
/// The base class for every <see cref="IMultipleRegistration{TInterface1,TInterface2, TImplementation}"/> to register multiple interfaces
/// The base class for every <see cref="IMultipleRegistration{TInterface1,TInterface2}"/> to register multiple interfaces
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal abstract class MultipleRegistration<TInterface1, TImplementation> : TypedRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TImplementation> where TImplementation : TInterface1
{
/// <summary>
/// The base class for every <see cref="IMultipleRegistration{TInterface1,TInterface2}"/> to register multiple interfaces
/// </summary>
/// <param name="interfaceType1">The <see cref="Type"/> of the first interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
protected MultipleRegistration(Type interfaceType1, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container) =>
Registrations = new List<IRegistration>();
/// <summary>
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="MultipleRegistration{TInterface1,TInterface2}"/>
/// </summary>
public List<IRegistration> Registrations { get; protected init; }
}
/// <param name="interfaceType1">The <see cref="Type"/> of the first interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
protected MultipleRegistration(Type interfaceType1, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container) =>
Registrations = new List<IRegistration>();
/// <summary>
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="MultipleRegistration{TInterface1,TInterface2}"/>
/// </summary>
public List<IRegistration> Registrations { get; protected init; }
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TImplementation> where TImplementation : TInterface1, TInterface2
/// <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="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </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="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
Registrations = new List<IRegistration>
{
Registrations = new List<IRegistration>
{
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container)
};
}
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container)
};
}
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
{
foreach (IRegistration registration in Registrations)
{
foreach (IRegistration registration in Registrations)
{
if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> where TImplementation : TInterface3, TInterface2, TInterface1
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> where TImplementation : TInterface3, TInterface2, TInterface1
/// <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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
Registrations = new List<IRegistration>
{
Registrations = new List<IRegistration>
{
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container)
};
}
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container)
};
}
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
{
foreach (IRegistration registration in Registrations)
{
foreach (IRegistration registration in Registrations)
{
if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1
/// <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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="interfaceType4">The <see cref="Type"/> of the fourth interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="interfaceType4">The <see cref="Type"/> of the fourth interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
Registrations = new List<IRegistration>
{
Registrations = new List<IRegistration>
{
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container),
new TypedRegistration<TInterface4, TImplementation>(interfaceType4, implementationType, lifestyle, container)
};
}
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container),
new TypedRegistration<TInterface4, TImplementation>(interfaceType4, implementationType, lifestyle, container)
};
}
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
{
foreach (IRegistration registration in Registrations)
{
foreach (IRegistration registration in Registrations)
{
if (registration is ITypedRegistration<TInterface4, TImplementation> interface4Registration)
interface4Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
if (registration is ITypedRegistration<TInterface4, TImplementation> interface4Registration)
interface4Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TInterface5">The fifth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </summary>
/// <typeparam name="TInterface1">The first interface</typeparam>
/// <typeparam name="TInterface2">The second interface</typeparam>
/// <typeparam name="TInterface3">The third interface</typeparam>
/// <typeparam name="TInterface4">The fourth interface</typeparam>
/// <typeparam name="TInterface5">The fifth interface</typeparam>
/// <typeparam name="TImplementation">The implementation</typeparam>
internal class MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> : MultipleRegistration<TInterface1, TImplementation>, IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1
/// <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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="interfaceType4">The <see cref="Type"/> of the fourth interface</param>
/// <param name="interfaceType5">The <see cref="Type"/> of the fifth interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type interfaceType5, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
{
/// <summary>
/// An <see cref="IRegistration"/> to register multiple interfaces for on implementation type
/// </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="interfaceType3">The <see cref="Type"/> of the third interface</param>
/// <param name="interfaceType4">The <see cref="Type"/> of the fourth interface</param>
/// <param name="interfaceType5">The <see cref="Type"/> of the fifth interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="MultipleRegistration{TInterface1,TInterface2}"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type interfaceType5, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType1, implementationType, lifestyle, container)
Registrations = new List<IRegistration>
{
Registrations = new List<IRegistration>
{
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container),
new TypedRegistration<TInterface4, TImplementation>(interfaceType4, implementationType, lifestyle, container),
new TypedRegistration<TInterface5, TImplementation>(interfaceType5, implementationType, lifestyle, container)
};
}
new TypedRegistration<TInterface1, TImplementation>(interfaceType1, implementationType, lifestyle, container),
new TypedRegistration<TInterface2, TImplementation>(interfaceType2, implementationType, lifestyle, container),
new TypedRegistration<TInterface3, TImplementation>(interfaceType3, implementationType, lifestyle, container),
new TypedRegistration<TInterface4, TImplementation>(interfaceType4, implementationType, lifestyle, container),
new TypedRegistration<TInterface5, TImplementation>(interfaceType5, implementationType, lifestyle, container)
};
}
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public override ITypedRegistration<TInterface1, TImplementation> OnCreate(Action<TImplementation?> action)
{
foreach (IRegistration registration in Registrations)
{
foreach (IRegistration registration in Registrations)
{
if (registration is ITypedRegistration<TInterface5, TImplementation> interface5Registration)
interface5Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface4, TImplementation> interface4Registration)
interface4Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
if (registration is ITypedRegistration<TInterface5, TImplementation> interface5Registration)
interface5Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface4, TImplementation> interface4Registration)
interface4Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface3, TImplementation> interface3Registration)
interface3Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface2, TImplementation> interface2Registration)
interface2Registration.OnCreate(action);
else if (registration is ITypedRegistration<TInterface1, TImplementation> interface1Registration)
interface1Registration.OnCreate(action);
}
return this;
}
}

@ -8,52 +8,51 @@ using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// The registration that is used to register a multiton
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
internal class MultitonRegistration<TInterface, TImplementation> : TypedRegistration<TInterface, TImplementation>, IMultitonRegistration<TInterface, TImplementation> where TImplementation : TInterface
{
/// <summary>
/// The registration that is used to register a multiton
/// </summary>
/// <typeparam name="TInterface">The registered interface</typeparam>
/// <typeparam name="TImplementation">The registered implementation</typeparam>
internal class MultitonRegistration<TInterface, TImplementation> : TypedRegistration<TInterface, TImplementation>, IMultitonRegistration<TInterface, TImplementation> where TImplementation : TInterface
/// <param name="interfaceType">The <see cref="Type"/> of the 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>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultitonRegistration(Type interfaceType, Type implementationType, Type scope, IocContainer container)
: base(interfaceType, implementationType, Lifestyle.Multiton, container) =>
Scope = scope;
/// <summary>
/// The <see cref="Type"/> of the multiton scope
/// </summary>
public Type Scope { get; }
/// <summary>
/// Validate the <see cref="RegistrationBase.Factory"/>
/// </summary>
protected override void ValidateFactory()
{
/// <summary>
/// The registration that is used to register a multiton
/// </summary>
/// <param name="interfaceType">The <see cref="Type"/> of the 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>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public MultitonRegistration(Type interfaceType, Type implementationType, Type scope, IocContainer container)
: base(interfaceType, implementationType, Lifestyle.Multiton, container) =>
Scope = scope;
/// <summary>
/// The <see cref="Type"/> of the multiton scope
/// </summary>
public Type Scope { get; }
/// <summary>
/// Validate the <see cref="RegistrationBase.Factory"/>
/// </summary>
protected override void ValidateFactory()
{
if (Factory == null)
return;
if (Factory.CreateMethods.Any(c => c.GetParameters().Length == 0))
throw new InvalidFactoryRegistrationException($"Create methods without parameters are not valid for multitons (Type: {InterfaceType}).");
if (Factory.CreateMethods.Any(c => c.GetParameters()[0].ParameterType != Scope))
throw new InvalidFactoryRegistrationException($"Create methods without scope type ({Scope}) as first parameter are not valid for multitons (Type: {InterfaceType}).");
base.ValidateFactory();
}
public override bool Equals(object? obj) => obj is MultitonRegistration<TInterface, TImplementation> multitonRegistration &&
base.Equals(obj) &&
Scope == multitonRegistration.Scope;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Scope);
if (Factory == null)
return;
if (Factory.CreateMethods.Any(c => c.GetParameters().Length == 0))
throw new InvalidFactoryRegistrationException($"Create methods without parameters are not valid for multitons (Type: {InterfaceType}).");
if (Factory.CreateMethods.Any(c => c.GetParameters()[0].ParameterType != Scope))
throw new InvalidFactoryRegistrationException($"Create methods without scope type ({Scope}) as first parameter are not valid for multitons (Type: {InterfaceType}).");
base.ValidateFactory();
}
public override bool Equals(object? obj) => obj is MultitonRegistration<TInterface, TImplementation> multitonRegistration &&
base.Equals(obj) &&
Scope == multitonRegistration.Scope;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Scope);
}

@ -7,47 +7,46 @@ using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// <see cref="IRegistration"/> for open generic types
/// </summary>
internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistration
{
/// <summary>
/// <see cref="IRegistration"/> for open generic types
/// </summary>
internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistration
/// <param name="interfaceType">The <see cref="Type"/> of the interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation type</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="IOpenGenericRegistration"/></param>
/// <param name="iocContainer">The current instance of the <see cref="IIocContainer"/></param>
public OpenGenericRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer iocContainer)
: base(interfaceType, lifestyle, iocContainer) =>
ImplementationType = implementationType;
/// <summary>
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IOpenGenericRegistration"/>
/// </summary>
public Type ImplementationType { get; }
/// <summary>
/// Validate this <see cref="OpenGenericRegistration"/>
/// </summary>
public override void Validate()
{
/// <summary>
/// <see cref="IRegistration"/> for open generic types
/// </summary>
/// <param name="interfaceType">The <see cref="Type"/> of the interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation type</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="IOpenGenericRegistration"/></param>
/// <param name="iocContainer">The current instance of the <see cref="IIocContainer"/></param>
public OpenGenericRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer iocContainer)
: base(interfaceType, lifestyle, iocContainer) =>
ImplementationType = implementationType;
/// <summary>
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IOpenGenericRegistration"/>
/// </summary>
public Type ImplementationType { get; }
/// <summary>
/// Validate this <see cref="OpenGenericRegistration"/>
/// </summary>
public override void Validate()
{
if (!InterfaceType.ContainsGenericParameters)
throw new InvalidRegistrationException("This function can only be used to register open generic types.");
if (Lifestyle == Lifestyle.Multiton)
throw new InvalidRegistrationException("Can't register a multiton with open generic registration."); //TODO: Is there any need to register multitons with open generics?
base.Validate();
}
public override bool Equals(object? obj) => obj is OpenGenericRegistration openGenericRegistration &&
base.Equals(obj) &&
ImplementationType == openGenericRegistration.ImplementationType;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ImplementationType);
if (!InterfaceType.ContainsGenericParameters)
throw new InvalidRegistrationException("This function can only be used to register open generic types.");
if (Lifestyle == Lifestyle.Multiton)
throw new InvalidRegistrationException("Can't register a multiton with open generic registration."); //TODO: Is there any need to register multitons with open generics?
base.Validate();
}
public override bool Equals(object? obj) => obj is OpenGenericRegistration openGenericRegistration &&
base.Equals(obj) &&
ImplementationType == openGenericRegistration.ImplementationType;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ImplementationType);
}

@ -12,236 +12,235 @@ using LightweightIocContainer.Interfaces.Registrations;
using LightweightIocContainer.Interfaces.Registrations.Fluent;
using LightweightIocContainer.ResolvePlaceholders;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// The <see cref="RegistrationBase"/> that is used to register an Interface
/// </summary>
internal abstract class RegistrationBase : IRegistrationBase, IWithFactoryInternal, IWithParametersInternal, ILifestyleProvider, IWithDisposeStrategyInternal, IInternalValidationProvider
{
private readonly IocContainer _container;
/// <summary>
/// The <see cref="RegistrationBase"/> that is used to register an Interface
/// </summary>
internal abstract class RegistrationBase : IRegistrationBase, IWithFactoryInternal, IWithParametersInternal, ILifestyleProvider, IWithDisposeStrategyInternal, IInternalValidationProvider
/// <param name="interfaceType">The <see cref="Type"/> of the Interface</param>
/// <param name="lifestyle">The <see cref="LightweightIocContainer.Lifestyle"/> of the registration</param>
/// <param name="container">The current instance of the <see cref="IocContainer"/></param>
protected RegistrationBase(Type interfaceType, Lifestyle lifestyle, IocContainer container)
{
private readonly IocContainer _container;
/// <summary>
/// The <see cref="RegistrationBase"/> that is used to register an Interface
/// </summary>
/// <param name="interfaceType">The <see cref="Type"/> of the Interface</param>
/// <param name="lifestyle">The <see cref="LightweightIocContainer.Lifestyle"/> of the registration</param>
/// <param name="container">The current instance of the <see cref="IocContainer"/></param>
protected RegistrationBase(Type interfaceType, Lifestyle lifestyle, IocContainer container)
{
InterfaceType = interfaceType;
Lifestyle = lifestyle;
_container = container;
}
InterfaceType = interfaceType;
Lifestyle = lifestyle;
_container = container;
}
/// <summary>
/// The <see cref="Type"/> of the Interface that is registered with this <see cref="RegistrationBase"/>
/// </summary>
public Type InterfaceType { get; }
/// <summary>
/// The <see cref="LightweightIocContainer.Lifestyle"/> of Instances that are created with this <see cref="RegistrationBase"/>
/// </summary>
public Lifestyle Lifestyle { get; }
/// <summary>
/// The <see cref="LightweightIocContainer.DisposeStrategy"/> of singletons/multitons that implement <see cref="IDisposable"/> and are created with this <see cref="RegistrationBase"/>
/// </summary>
public DisposeStrategy DisposeStrategy { get; private set; }
/// <summary>
/// An <see cref="Array"/> of parameters that are used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="WithParameters(object[])"/></para>
/// </summary>
public object[]? Parameters { get; private set; }
/// <summary>
/// The Factory added with the <see cref="WithFactory{TFactory}"/> method
/// </summary>
public ITypedFactory? Factory { get; private set; }
/// <summary>
/// Pass parameters that will be used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters</param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="Parameters"/> are already set or no parameters given</exception>
public virtual IRegistrationBase WithParameters(params object[] parameters)
{
if (Parameters != null)
throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
/// <summary>
/// The <see cref="Type"/> of the Interface that is registered with this <see cref="RegistrationBase"/>
/// </summary>
public Type InterfaceType { get; }
if (parameters == null || !parameters.Any())
throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
/// <summary>
/// The <see cref="LightweightIocContainer.Lifestyle"/> of Instances that are created with this <see cref="RegistrationBase"/>
/// </summary>
public Lifestyle Lifestyle { get; }
Parameters = parameters;
return this;
}
/// <summary>
/// The <see cref="LightweightIocContainer.DisposeStrategy"/> of singletons/multitons that implement <see cref="IDisposable"/> and are created with this <see cref="RegistrationBase"/>
/// </summary>
public DisposeStrategy DisposeStrategy { get; private set; }
/// <summary>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters with their position</param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="Parameters"/> are already set or no parameters given</exception>
public virtual IRegistrationBase WithParameters(params (int index, object parameter)[] parameters)
{
if (Parameters != null)
throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
/// <summary>
/// An <see cref="Array"/> of parameters that are used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="WithParameters(object[])"/></para>
/// </summary>
public object[]? Parameters { get; private set; }
if (parameters == null || !parameters.Any())
throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
/// <summary>
/// The Factory added with the <see cref="WithFactory{TFactory}"/> method
/// </summary>
public ITypedFactory? Factory { get; private set; }
int lastIndex = parameters.Max(p => p.index);
Parameters = new object[lastIndex + 1];
/// <summary>
/// Pass parameters that will be used to <see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters</param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="Parameters"/> are already set or no parameters given</exception>
public virtual IRegistrationBase WithParameters(params object[] parameters)
{
if (Parameters != null)
throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
for (int i = 0; i < Parameters.Length; i++)
{
if (parameters.Any(p => p.index == i))
Parameters[i] = parameters.First(p => p.index == i).parameter;
else
Parameters[i] = new InternalResolvePlaceholder();
}
if (parameters == null || !parameters.Any())
throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
return this;
}
Parameters = parameters;
return this;
}
/// <summary>
/// Register an abstract typed factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
public IRegistrationBase WithFactory<TFactory>()
{
TypedFactory<TFactory> factory = new(_container);
Factory = factory;
/// <summary>
/// Pass parameters that will be used to<see cref="IocContainer.Resolve{T}()"/> an instance of this <see cref="IRegistration.InterfaceType"/>
/// <para>Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving</para>
/// </summary>
/// <param name="parameters">The parameters with their position</param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
/// <exception cref="InvalidRegistrationException"><see cref="Parameters"/> are already set or no parameters given</exception>
public virtual IRegistrationBase WithParameters(params (int index, object parameter)[] parameters)
{
if (Parameters != null)
throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
_container.RegisterFactory(factory);
if (parameters == null || !parameters.Any())
throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
return this;
}
int lastIndex = parameters.Max(p => p.index);
Parameters = new object[lastIndex + 1];
/// <summary>
/// Register a custom implemented factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactoryInterface">The type of the interface for the custom factory</typeparam>
/// <typeparam name="TFactoryImplementation">The type of the implementation for the custom factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
public IRegistrationBase WithFactory<TFactoryInterface, TFactoryImplementation>() where TFactoryImplementation : TFactoryInterface
for (int i = 0; i < Parameters.Length; i++)
{
Factory = new CustomTypedFactory<TFactoryInterface>();
_container.Register(r => r.Add<TFactoryInterface, TFactoryImplementation>());
return this;
if (parameters.Any(p => p.index == i))
Parameters[i] = parameters.First(p => p.index == i).parameter;
else
Parameters[i] = new InternalResolvePlaceholder();
}
/// <summary>
/// Add a <see cref="DisposeStrategy"/> for the <see cref="IRegistrationBase"/>
/// </summary>
/// <param name="disposeStrategy">The <see cref="DisposeStrategy"/></param>
/// <returns>The current instance of this <see cref="RegistrationBase"/></returns>
public IRegistrationBase WithDisposeStrategy(DisposeStrategy disposeStrategy)
{
DisposeStrategy = disposeStrategy;
return this;
}
return this;
}
/// <summary>
/// Validate this <see cref="RegistrationBase"/>
/// </summary>
public virtual void Validate()
{
ValidateMultiton();
ValidateFactory();
ValidateDisposeStrategy();
}
/// <summary>
/// Register an abstract typed factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactory">The type of the abstract typed factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
public IRegistrationBase WithFactory<TFactory>()
{
TypedFactory<TFactory> factory = new(_container);
Factory = factory;
/// <summary>
/// Validate that no registration that isn't derived from <see cref="IMultitonRegistration"/> has <see cref="LightweightIocContainer.Lifestyle.Multiton"/>
/// </summary>
/// <exception cref="InvalidRegistrationException"></exception>
private void ValidateMultiton()
{
//don't allow lifestyle.multiton without iMultitonRegistration
if (Lifestyle == Lifestyle.Multiton && this is not IMultitonRegistration)
throw new InvalidRegistrationException("Can't register a type as Lifestyle.Multiton without a scope (Registration is not of type IMultitonRegistration).");
}
_container.RegisterFactory(factory);
/// <summary>
/// Validate the <see cref="Factory"/>
/// </summary>
/// <exception cref="InvalidFactoryRegistrationException">No create method that can create the <see cref="InterfaceType"/></exception>
protected virtual void ValidateFactory()
{
if (Factory == null)
return;
return this;
}
if (Factory.CreateMethods.All(c => c.ReturnType != InterfaceType))
throw new InvalidFactoryRegistrationException($"No create method that can create {InterfaceType}.");
}
/// <summary>
/// Register a custom implemented factory for the <see cref="IRegistrationBase"/>
/// </summary>
/// <typeparam name="TFactoryInterface">The type of the interface for the custom factory</typeparam>
/// <typeparam name="TFactoryImplementation">The type of the implementation for the custom factory</typeparam>
/// <returns>The current instance of this <see cref="IRegistrationBase"/></returns>
public IRegistrationBase WithFactory<TFactoryInterface, TFactoryImplementation>() where TFactoryImplementation : TFactoryInterface
{
Factory = new CustomTypedFactory<TFactoryInterface>();
_container.Register(r => r.Add<TFactoryInterface, TFactoryImplementation>());
return this;
}
/// <summary>
/// Add a <see cref="DisposeStrategy"/> for the <see cref="IRegistrationBase"/>
/// </summary>
/// <param name="disposeStrategy">The <see cref="DisposeStrategy"/></param>
/// <returns>The current instance of this <see cref="RegistrationBase"/></returns>
public IRegistrationBase WithDisposeStrategy(DisposeStrategy disposeStrategy)
{
DisposeStrategy = disposeStrategy;
return this;
}
/// <summary>
/// Validate this <see cref="RegistrationBase"/>
/// </summary>
public virtual void Validate()
{
ValidateMultiton();
ValidateFactory();
ValidateDisposeStrategy();
}
/// <summary>
/// Validate that no registration that isn't derived from <see cref="IMultitonRegistration"/> has <see cref="LightweightIocContainer.Lifestyle.Multiton"/>
/// </summary>
/// <exception cref="InvalidRegistrationException"></exception>
private void ValidateMultiton()
{
//don't allow lifestyle.multiton without iMultitonRegistration
if (Lifestyle == Lifestyle.Multiton && this is not IMultitonRegistration)
throw new InvalidRegistrationException("Can't register a type as Lifestyle.Multiton without a scope (Registration is not of type IMultitonRegistration).");
}
/// <summary>
/// Validate the <see cref="Factory"/>
/// </summary>
/// <exception cref="InvalidFactoryRegistrationException">No create method that can create the <see cref="InterfaceType"/></exception>
protected virtual void ValidateFactory()
{
if (Factory == null)
return;
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the <see cref="InterfaceType"/> and <see cref="Lifestyle"/>
/// </summary>
protected virtual void ValidateDisposeStrategy() => ValidateDisposeStrategy(InterfaceType);
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the given <see cref="Type"/> and <see cref="Lifestyle"/>
/// </summary>
/// <param name="type">The given <see cref="Type"/></param>
/// <exception cref="InvalidDisposeStrategyException">Dispose strategy is invalid for this <see cref="InterfaceType"/> and <see cref="Lifestyle"/></exception>
protected void ValidateDisposeStrategy(Type type)
if (Factory.CreateMethods.All(c => c.ReturnType != InterfaceType))
throw new InvalidFactoryRegistrationException($"No create method that can create {InterfaceType}.");
}
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the <see cref="InterfaceType"/> and <see cref="Lifestyle"/>
/// </summary>
protected virtual void ValidateDisposeStrategy() => ValidateDisposeStrategy(InterfaceType);
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the given <see cref="Type"/> and <see cref="Lifestyle"/>
/// </summary>
/// <param name="type">The given <see cref="Type"/></param>
/// <exception cref="InvalidDisposeStrategyException">Dispose strategy is invalid for this <see cref="InterfaceType"/> and <see cref="Lifestyle"/></exception>
protected void ValidateDisposeStrategy(Type type)
{
if (Lifestyle == Lifestyle.Transient)
{
if (Lifestyle == Lifestyle.Transient)
if (DisposeStrategy != DisposeStrategy.None)
throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle);
}
else
{
if (type.IsAssignableTo(typeof(IDisposable)))
{
if (DisposeStrategy != DisposeStrategy.None)
if (DisposeStrategy == DisposeStrategy.None)
throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle);
}
else
{
if (type.IsAssignableTo(typeof(IDisposable)))
{
if (DisposeStrategy == DisposeStrategy.None)
throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle);
}
else
{
if (DisposeStrategy != DisposeStrategy.None)
throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle);
}
if (DisposeStrategy != DisposeStrategy.None)
throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle);
}
}
}
public override bool Equals(object? obj)
{
if (obj is not RegistrationBase registrationBase)
return false;
if (Parameters == null && registrationBase.Parameters != null)
return false;
public override bool Equals(object? obj)
{
if (obj is not RegistrationBase registrationBase)
return false;
if (Parameters != null && registrationBase.Parameters == null)
return false;
if (Parameters == null && registrationBase.Parameters != null)
return false;
if (Parameters?.Length != registrationBase.Parameters?.Length)
return false;
if (Parameters != null && registrationBase.Parameters == null)
return false;
if (Factory == null && registrationBase.Factory != null)
return false;
if (Parameters?.Length != registrationBase.Parameters?.Length)
return false;
if (Factory != null && registrationBase.Factory == null)
return false;
if (Factory == null && registrationBase.Factory != null)
return false;
if (Factory?.CreateMethods.Count != registrationBase.Factory?.CreateMethods.Count)
return false;
if (Factory != null && registrationBase.Factory == null)
return false;
return InterfaceType == registrationBase.InterfaceType &&
Lifestyle == registrationBase.Lifestyle &&
DisposeStrategy == registrationBase.DisposeStrategy;
}
if (Factory?.CreateMethods.Count != registrationBase.Factory?.CreateMethods.Count)
return false;
public override int GetHashCode() => HashCode.Combine(InterfaceType, (int) Lifestyle);
return InterfaceType == registrationBase.InterfaceType &&
Lifestyle == registrationBase.Lifestyle &&
DisposeStrategy == registrationBase.DisposeStrategy;
}
public override int GetHashCode() => HashCode.Combine(InterfaceType, (int) Lifestyle);
}

@ -7,121 +7,120 @@ using LightweightIocContainer.Interfaces.Factories;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// A factory to register interfaces and factories in an <see cref="IIocInstaller"/> and create the needed <see cref="IRegistration"/>s
/// </summary>
internal class RegistrationFactory
{
/// <summary>
/// A factory to register interfaces and factories in an <see cref="IIocInstaller"/> and create the needed <see cref="IRegistration"/>s
/// </summary>
internal class RegistrationFactory
{
private readonly IocContainer _iocContainer;
private readonly IocContainer _iocContainer;
internal RegistrationFactory(IocContainer container) => _iocContainer = container;
internal RegistrationFactory(IocContainer container) => _iocContainer = container;
/// <summary>
/// Register an Interface with a Type that implements it and create a <see cref="ITypedRegistration{TInterface,TImplementation}"/>
/// </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="ITypedRegistration{TInterface,TImplementation}"/></param>
/// <returns>A new created <see cref="ITypedRegistration{TInterface,TImplementation}"/> with the given parameters</returns>
public ITypedRegistration<TInterface, TImplementation> Register<TInterface, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface =>
new TypedRegistration<TInterface, TImplementation>(typeof(TInterface), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register an Interface with a Type that implements it and create a <see cref="ITypedRegistration{TInterface,TImplementation}"/>
/// </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="ITypedRegistration{TInterface,TImplementation}"/></param>
/// <returns>A new created <see cref="ITypedRegistration{TInterface,TImplementation}"/> with the given parameters</returns>
public ITypedRegistration<TInterface, TImplementation> Register<TInterface, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface =>
new TypedRegistration<TInterface, TImplementation>(typeof(TInterface), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register an open generic Interface with an open generic Type that implements it and create a <see cref="IOpenGenericRegistration"/>
/// </summary>
/// <param name="tInterface">The open generic Interface to register</param>
/// <param name="tImplementation">The open generic Type that implements the interface</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IOpenGenericRegistration"/></param>
/// <returns>The created <see cref="IOpenGenericRegistration"/></returns>
public IOpenGenericRegistration Register(Type tInterface, Type tImplementation, Lifestyle lifestyle) =>
new OpenGenericRegistration(tInterface, tImplementation, lifestyle, _iocContainer);
/// <summary>
/// Register an open generic Interface with an open generic Type that implements it and create a <see cref="IOpenGenericRegistration"/>
/// </summary>
/// <param name="tInterface">The open generic Interface to register</param>
/// <param name="tImplementation">The open generic Type that implements the interface</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="IOpenGenericRegistration"/></param>
/// <returns>The created <see cref="IOpenGenericRegistration"/></returns>
public IOpenGenericRegistration Register(Type tInterface, Type tImplementation, Lifestyle lifestyle) =>
new OpenGenericRegistration(tInterface, tImplementation, lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2}"/>
/// </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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TImplementation> Register<TInterface1, TInterface2, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2 =>
new MultipleRegistration<TInterface1, TInterface2, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2}"/>
/// </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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TImplementation> Register<TInterface1, TInterface2, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2 =>
new MultipleRegistration<TInterface1, TInterface2, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> Register<TInterface1, TInterface2, TInterface3, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation> Register<TInterface1, TInterface2, TInterface3, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third interface to register</typeparam>
/// <typeparam name="TInterface4">A fourth 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> Register<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third interface to register</typeparam>
/// <typeparam name="TInterface4">A fourth 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation> Register<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4,TInterface5}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third interface to register</typeparam>
/// <typeparam name="TInterface4">A fourth interface to register</typeparam>
/// <typeparam name="TInterface5">A fifth 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4,TInterface5}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> Register<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4, TInterface5 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TInterface5), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register multiple interfaces for a <see cref="Type"/> that implements them and create a <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4,TInterface5}"/>
/// </summary>
/// <typeparam name="TInterface1">The base interface to register</typeparam>
/// <typeparam name="TInterface2">A second interface to register</typeparam>
/// <typeparam name="TInterface3">A third interface to register</typeparam>
/// <typeparam name="TInterface4">A fourth interface to register</typeparam>
/// <typeparam name="TInterface5">A fifth 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"/></param>
/// <returns>The created <see cref="IMultipleRegistration{TInterface1,TInterface2,TInterface3,TInterface4,TInterface5}"/></returns>
public IMultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation> Register<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation>(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4, TInterface5 =>
new MultipleRegistration<TInterface1, TInterface2, TInterface3, TInterface4, TInterface5, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TInterface5), typeof(TImplementation), lifestyle, _iocContainer);
/// <summary>
/// Register a <see cref="Type"/> without an interface and create a <see cref="ISingleTypeRegistration{TInterface}"/>
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> to register</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="ISingleTypeRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="ISingleTypeRegistration{TInterface}"/> with the given parameters</returns>
public ISingleTypeRegistration<T> Register<T>(Lifestyle lifestyle) => new SingleTypeRegistration<T>(typeof(T), lifestyle, _iocContainer);
/// <summary>
/// Register a <see cref="Type"/> without an interface and create a <see cref="ISingleTypeRegistration{TInterface}"/>
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> to register</typeparam>
/// <param name="lifestyle">The <see cref="Lifestyle"/> for this <see cref="ISingleTypeRegistration{TInterface}"/></param>
/// <returns>A new created <see cref="ISingleTypeRegistration{TInterface}"/> with the given parameters</returns>
public ISingleTypeRegistration<T> Register<T>(Lifestyle lifestyle) => new SingleTypeRegistration<T>(typeof(T), lifestyle, _iocContainer);
/// <summary>
/// Register an Interface with a Type that implements it as a multiton and create a <see cref="IMultitonRegistration{TInterface,TImplementation}"/>
/// </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>
/// <returns>A new created <see cref="IMultitonRegistration{TInterface,TImplementation}"/> with the given parameters</returns>
public IMultitonRegistration<TInterface, TImplementation> RegisterMultiton<TInterface, TImplementation, TScope>() where TImplementation : TInterface =>
new MultitonRegistration<TInterface, TImplementation>(typeof(TInterface), typeof(TImplementation), typeof(TScope), _iocContainer);
/// <summary>
/// Register an Interface with a Type that implements it as a multiton and create a <see cref="IMultitonRegistration{TInterface,TImplementation}"/>
/// </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>
/// <returns>A new created <see cref="IMultitonRegistration{TInterface,TImplementation}"/> with the given parameters</returns>
public IMultitonRegistration<TInterface, TImplementation> RegisterMultiton<TInterface, TImplementation, TScope>() where TImplementation : TInterface =>
new MultitonRegistration<TInterface, TImplementation>(typeof(TInterface), typeof(TImplementation), typeof(TScope), _iocContainer);
/// <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 =>
new MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope), _iocContainer);
/// <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 =>
new MultipleMultitonRegistration<TInterface1, TInterface2, TImplementation>(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope), _iocContainer);
/// <summary>
/// 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>
/// <returns>A new created <see cref="ITypedFactoryRegistration{TFactory}"/> with the given parameters</returns>
public ITypedFactoryRegistration<TFactory> RegisterFactory<TFactory>(ITypedFactory<TFactory> factory) => new TypedFactoryRegistration<TFactory>(factory);
}
/// <summary>
/// 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>
/// <returns>A new created <see cref="ITypedFactoryRegistration{TFactory}"/> with the given parameters</returns>
public ITypedFactoryRegistration<TFactory> RegisterFactory<TFactory>(ITypedFactory<TFactory> factory) => new TypedFactoryRegistration<TFactory>(factory);
}

@ -6,56 +6,55 @@ using System;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// The <see cref="IRegistration"/> to register either only an interface or only a <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the <see cref="IRegistration"/></typeparam>
internal class SingleTypeRegistration<T> : RegistrationBase, ISingleTypeRegistration<T>
{
/// <summary>
/// The <see cref="IRegistration"/> to register either only an interface or only a <see cref="Type"/>
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the <see cref="IRegistration"/></typeparam>
internal class SingleTypeRegistration<T> : RegistrationBase, ISingleTypeRegistration<T>
/// <param name="interfaceType">The <see cref="Type"/> of the interface or <see cref="Type"/></param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of the <see cref="RegistrationBase"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType, lifestyle, container)
{
/// <summary>
/// The <see cref="IRegistration"/> to register either only an interface or only a <see cref="Type"/>
/// </summary>
/// <param name="interfaceType">The <see cref="Type"/> of the interface or <see cref="Type"/></param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of the <see cref="RegistrationBase"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType, lifestyle, container)
{
}
/// <summary>
/// <see cref="Func{T,TResult}"/> that is invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
public Func<IIocResolver, T>? FactoryMethod { get; private set; }
/// <summary>
/// Pass a <see cref="Func{T,TResult}"/> that will be invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
/// <param name="factoryMethod">The <see cref="Func{T,TResult}"/></param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
public ISingleTypeRegistration<T> WithFactoryMethod(Func<IIocResolver, T> factoryMethod)
{
FactoryMethod = factoryMethod;
return this;
}
public override bool Equals(object? obj)
{
if (obj is not SingleTypeRegistration<T> singleTypeRegistration)
return false;
if (FactoryMethod == null && singleTypeRegistration.FactoryMethod != null)
return false;
if (FactoryMethod != null && singleTypeRegistration.FactoryMethod == null)
return false;
return base.Equals(obj);
}
public override int GetHashCode() => base.GetHashCode();
}
/// <summary>
/// <see cref="Func{T,TResult}"/> that is invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
public Func<IIocResolver, T>? FactoryMethod { get; private set; }
/// <summary>
/// Pass a <see cref="Func{T,TResult}"/> that will be invoked instead of creating an instance of this <see cref="Type"/> the default way
/// </summary>
/// <param name="factoryMethod">The <see cref="Func{T,TResult}"/></param>
/// <returns>The current instance of this <see cref="IRegistration"/></returns>
public ISingleTypeRegistration<T> WithFactoryMethod(Func<IIocResolver, T> factoryMethod)
{
FactoryMethod = factoryMethod;
return this;
}
public override bool Equals(object? obj)
{
if (obj is not SingleTypeRegistration<T> singleTypeRegistration)
return false;
if (FactoryMethod == null && singleTypeRegistration.FactoryMethod != null)
return false;
if (FactoryMethod != null && singleTypeRegistration.FactoryMethod == null)
return false;
return base.Equals(obj);
}
public override int GetHashCode() => base.GetHashCode();
}

@ -6,34 +6,33 @@ using System;
using LightweightIocContainer.Interfaces.Factories;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// The registration that is used to register an abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The <see cref="Type"/> of the abstract typed factory</typeparam>
internal class TypedFactoryRegistration<TFactory> : ITypedFactoryRegistration<TFactory>
{
/// <summary>
/// The registration that is used to register an abstract typed factory
/// </summary>
/// <typeparam name="TFactory">The <see cref="Type"/> of the abstract typed factory</typeparam>
internal class TypedFactoryRegistration<TFactory> : ITypedFactoryRegistration<TFactory>
{
/// <summary>
/// The registration that is used to register an abstract typed factory
/// </summary>
/// <param name="factory">The <see cref="ITypedFactory{TFactory}"/> for this <see cref="IRegistration"/></param>
public TypedFactoryRegistration(ITypedFactory<TFactory> factory) => Factory = factory;
/// <param name="factory">The <see cref="ITypedFactory{TFactory}"/> for this <see cref="IRegistration"/></param>
public TypedFactoryRegistration(ITypedFactory<TFactory> factory) => Factory = factory;
/// <summary>
/// The <see cref="Type"/> of the factory that is registered with this <see cref="IRegistration"/>
/// </summary>
public Type InterfaceType => typeof(TFactory);
/// <summary>
/// The <see cref="Type"/> of the factory that is registered with this <see cref="IRegistration"/>
/// </summary>
public Type InterfaceType => typeof(TFactory);
/// <summary>
/// The class that contains the implemented abstract factory of this <see cref="TypedFactoryRegistration{TFactory}"/>
/// </summary>
public ITypedFactory<TFactory> Factory { get; }
/// <summary>
/// The class that contains the implemented abstract factory of this <see cref="TypedFactoryRegistration{TFactory}"/>
/// </summary>
public ITypedFactory<TFactory> Factory { get; }
public override bool Equals(object? obj) => obj is TypedFactoryRegistration<TFactory> factoryRegistration &&
Factory.CreateMethods.Count == factoryRegistration.Factory.CreateMethods.Count &&
InterfaceType == factoryRegistration.InterfaceType;
public override bool Equals(object? obj) => obj is TypedFactoryRegistration<TFactory> factoryRegistration &&
Factory.CreateMethods.Count == factoryRegistration.Factory.CreateMethods.Count &&
InterfaceType == factoryRegistration.InterfaceType;
public override int GetHashCode() => HashCode.Combine(InterfaceType);
}
public override int GetHashCode() => HashCode.Combine(InterfaceType);
}

@ -8,74 +8,73 @@ using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
using LightweightIocContainer.Interfaces.Registrations.Fluent;
namespace LightweightIocContainer.Registrations
namespace LightweightIocContainer.Registrations;
/// <summary>
/// A <see cref="IRegistrationBase"/> that implements a <see cref="Type"/>
/// </summary>
internal class TypedRegistration<TInterface, TImplementation> : RegistrationBase, ITypedRegistration<TInterface, TImplementation> where TImplementation : TInterface
{
/// <summary>
/// A <see cref="IRegistrationBase"/> that implements a <see cref="Type"/>
/// </summary>
internal class TypedRegistration<TInterface, TImplementation> : RegistrationBase, ITypedRegistration<TInterface, TImplementation> where TImplementation : TInterface
{
/// <summary>
/// A <see cref="IRegistrationBase"/> that implements a <see cref="Type"/>
/// </summary>
/// <param name="interfaceType">The <see cref="Type"/> of the interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation type</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="IRegistrationBase"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public TypedRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType, lifestyle, container) =>
ImplementationType = implementationType;
/// <summary>
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IRegistrationBase"/>
/// </summary>
public Type ImplementationType { get; }
/// <param name="interfaceType">The <see cref="Type"/> of the interface</param>
/// <param name="implementationType">The <see cref="Type"/> of the implementation type</param>
/// <param name="lifestyle">The <see cref="Lifestyle"/> of this <see cref="IRegistrationBase"/></param>
/// <param name="container">The current instance of the <see cref="IIocContainer"/></param>
public TypedRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer container)
: base(interfaceType, lifestyle, container) =>
ImplementationType = implementationType;
/// <summary>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface,TImplementation}.OnCreate"/></para>
/// </summary>
private Action<object?>? OnCreateAction { get; set; }
/// <summary>
/// The <see cref="Type"/> that implements the <see cref="IRegistration.InterfaceType"/> that is registered with this <see cref="IRegistrationBase"/>
/// </summary>
public Type ImplementationType { get; }
/// <summary>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface,TImplementation}.OnCreate"/></para>
/// </summary>
Action<object?>? IOnCreate.OnCreateAction => OnCreateAction;
/// <summary>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface,TImplementation}.OnCreate"/></para>
/// </summary>
private Action<object?>? OnCreateAction { get; set; }
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public virtual ITypedRegistration<TInterface, TImplementation> OnCreate(Action<TImplementation?> action)
{
OnCreateAction = a => action((TImplementation?) a);
return this;
}
/// <summary>
/// This <see cref="Action"/> is invoked when an instance of this type is created.
/// <para>Can be set in the <see cref="IIocInstaller"/> by calling <see cref="IOnCreate{TInterface,TImplementation}.OnCreate"/></para>
/// </summary>
Action<object?>? IOnCreate.OnCreateAction => OnCreateAction;
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the <see cref="ImplementationType"/> and <see cref="Lifestyle"/>
/// </summary>
protected override void ValidateDisposeStrategy() => ValidateDisposeStrategy(ImplementationType);
/// <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="ITypedRegistration{TInterface,TImplementation}"/></returns>
public virtual ITypedRegistration<TInterface, TImplementation> OnCreate(Action<TImplementation?> action)
{
OnCreateAction = a => action((TImplementation?) a);
return this;
}
public override bool Equals(object? obj)
{
if (obj is not TypedRegistration<TInterface, TImplementation> typedRegistration)
return false;
/// <summary>
/// Validate the <see cref="DisposeStrategy"/> for the <see cref="ImplementationType"/> and <see cref="Lifestyle"/>
/// </summary>
protected override void ValidateDisposeStrategy() => ValidateDisposeStrategy(ImplementationType);
if (!base.Equals(obj))
return false;
public override bool Equals(object? obj)
{
if (obj is not TypedRegistration<TInterface, TImplementation> typedRegistration)
return false;
if (OnCreateAction == null && typedRegistration.OnCreateAction != null)
return false;
if (!base.Equals(obj))
return false;
if (OnCreateAction != null && typedRegistration.OnCreateAction == null)
return false;
if (OnCreateAction == null && typedRegistration.OnCreateAction != null)
return false;
return ImplementationType == typedRegistration.ImplementationType;
}
if (OnCreateAction != null && typedRegistration.OnCreateAction == null)
return false;
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ImplementationType);
return ImplementationType == typedRegistration.ImplementationType;
}
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ImplementationType);
}

@ -2,13 +2,12 @@
// Created: 2019-11-22
// Copyright(c) 2019 SimonG. All Rights Reserved.
namespace LightweightIocContainer.ResolvePlaceholders
namespace LightweightIocContainer.ResolvePlaceholders;
/// <summary>
/// An internal placeholder that is used during the resolving process
/// </summary>
internal class InternalResolvePlaceholder
{
/// <summary>
/// An internal placeholder that is used during the resolving process
/// </summary>
internal class InternalResolvePlaceholder
{
}
}

@ -6,33 +6,32 @@ using System;
using System.Collections.Generic;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.ResolvePlaceholders
namespace LightweightIocContainer.ResolvePlaceholders;
/// <summary>
/// An internal placeholder that is used to hold types that need to be resolved during the resolving process
/// </summary>
internal class InternalToBeResolvedPlaceholder : IInternalToBeResolvedPlaceholder
{
/// <summary>
/// An internal placeholder that is used to hold types that need to be resolved during the resolving process
/// </summary>
internal class InternalToBeResolvedPlaceholder : IInternalToBeResolvedPlaceholder
public InternalToBeResolvedPlaceholder(Type resolvedType, IRegistration resolvedRegistration, List<object?>? parameters)
{
public InternalToBeResolvedPlaceholder(Type resolvedType, IRegistration resolvedRegistration, List<object?>? parameters)
{
ResolvedType = resolvedType;
ResolvedRegistration = resolvedRegistration;
Parameters = parameters;
}
ResolvedType = resolvedType;
ResolvedRegistration = resolvedRegistration;
Parameters = parameters;
}
/// <summary>
/// The <see cref="Type"/> to be resolved
/// </summary>
public Type ResolvedType { get; }
/// <summary>
/// The <see cref="Type"/> to be resolved
/// </summary>
public Type ResolvedType { get; }
/// <summary>
/// The <see cref="IRegistration"/> to be resolved
/// </summary>
public IRegistration ResolvedRegistration { get; }
/// <summary>
/// The <see cref="IRegistration"/> to be resolved
/// </summary>
public IRegistration ResolvedRegistration { get; }
/// <summary>
/// The parameters needed to resolve the <see cref="ResolvedRegistration"/>
/// </summary>
public List<object?>? Parameters { get; }
}
/// <summary>
/// The parameters needed to resolve the <see cref="ResolvedRegistration"/>
/// </summary>
public List<object?>? Parameters { get; }
}

@ -4,15 +4,14 @@
using System;
namespace LightweightIocContainer
namespace LightweightIocContainer;
internal static class TypeExtension
{
internal static class TypeExtension
{
/// <summary>
/// Returns the default value for a given <see cref="Type"/>
/// </summary>
/// <param name="type">The given <see cref="Type"/></param>
/// <returns>The default value for the given <see cref="Type"/></returns>
public static object? GetDefault(this Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
}
/// <summary>
/// Returns the default value for a given <see cref="Type"/>
/// </summary>
/// <param name="type">The given <see cref="Type"/></param>
/// <returns>The default value for the given <see cref="Type"/></returns>
public static object? GetDefault(this Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
}

@ -9,98 +9,97 @@ using LightweightIocContainer.Interfaces.Registrations;
using LightweightIocContainer.Interfaces.Registrations.Fluent;
using Moq;
namespace LightweightIocContainer.Validation
namespace LightweightIocContainer.Validation;
/// <summary>
/// Validator for your <see cref="IocContainer"/> to check if everything can be resolved with your current setup
/// </summary>
public class IocValidator
{
private readonly IocContainer _iocContainer;
private readonly List<(Type type, object? parameter)> _parameters;
/// <summary>
/// Validator for your <see cref="IocContainer"/> to check if everything can be resolved with your current setup
/// </summary>
public class IocValidator
/// <param name="iocContainer">The <see cref="IocContainer"/></param>
public IocValidator(IocContainer iocContainer)
{
private readonly IocContainer _iocContainer;
private readonly List<(Type type, object? parameter)> _parameters;
_iocContainer = iocContainer;
_parameters = new List<(Type, object?)>();
}
/// <summary>
/// Validator for your <see cref="IocContainer"/> to check if everything can be resolved with your current setup
/// </summary>
/// <param name="iocContainer">The <see cref="IocContainer"/></param>
public IocValidator(IocContainer iocContainer)
{
_iocContainer = iocContainer;
_parameters = new List<(Type, object?)>();
}
/// <summary>
/// Add parameters that can't be default for your type to be created successfully
/// </summary>
/// <param name="parameter">The new value of the parameter</param>
/// <typeparam name="TInterface">The <see cref="Type"/> of your registered interface</typeparam>
/// <typeparam name="TParameter">The <see cref="Type"/> of your <paramref name="parameter"></paramref></typeparam>
public void AddParameter<TInterface, TParameter>(TParameter parameter) => _parameters.Add((typeof(TInterface), parameter));
/// <summary>
/// Add parameters that can't be default for your type to be created successfully
/// </summary>
/// <param name="parameter">The new value of the parameter</param>
/// <typeparam name="TInterface">The <see cref="Type"/> of your registered interface</typeparam>
/// <typeparam name="TParameter">The <see cref="Type"/> of your <paramref name="parameter"></paramref></typeparam>
public void AddParameter<TInterface, TParameter>(TParameter parameter) => _parameters.Add((typeof(TInterface), parameter));
/// <summary>
/// Validates your given <see cref="IocContainer"/> and checks if everything can be resolved with the current setup
/// <exception cref="AggregateException">Collection of all exceptions that are thrown during validation</exception>
/// </summary>
public void Validate()
{
List<Exception> validationExceptions = new();
/// <summary>
/// Validates your given <see cref="IocContainer"/> and checks if everything can be resolved with the current setup
/// <exception cref="AggregateException">Collection of all exceptions that are thrown during validation</exception>
/// </summary>
public void Validate()
foreach (IRegistration registration in _iocContainer.Registrations)
{
List<Exception> validationExceptions = new();
var definedParameters = _parameters.Where(p => p.type == registration.InterfaceType);
foreach (IRegistration registration in _iocContainer.Registrations)
if (registration is IWithFactoryInternal { Factory: { } } withFactoryRegistration)
{
var definedParameters = _parameters.Where(p => p.type == registration.InterfaceType);
if (registration is IWithFactoryInternal { Factory: { } } withFactoryRegistration)
{
(from createMethod in withFactoryRegistration.Factory.CreateMethods
(from createMethod in withFactoryRegistration.Factory.CreateMethods
select createMethod.GetParameters().Select(p => p.ParameterType)
into parameterTypes
select (from parameterType in parameterTypes
let definedParameter = definedParameters
.FirstOrDefault(p => parameterType.IsInstanceOfType(p.parameter))
select definedParameter == default ? GetMockOrDefault(parameterType) : definedParameter.parameter).ToArray())
.ToList()
.ForEach(p => TryResolve(registration.InterfaceType, p, validationExceptions, true));
}
else
{
object?[] arguments = definedParameters.Select(p => p.parameter).ToArray();
TryResolve(registration.InterfaceType, arguments, validationExceptions);
}
}
if (validationExceptions.Any())
throw new AggregateException("Validation failed.", validationExceptions);
}
private void TryResolve(Type type, object?[]? arguments, List<Exception> validationExceptions, bool isFactoryResolve = false)
{
try
{
_iocContainer.TryResolveNonGeneric(type, arguments, null, isFactoryResolve);
.ToList()
.ForEach(p => TryResolve(registration.InterfaceType, p, validationExceptions, true));
}
catch (Exception exception)
else
{
validationExceptions.Add(exception);
object?[] arguments = definedParameters.Select(p => p.parameter).ToArray();
TryResolve(registration.InterfaceType, arguments, validationExceptions);
}
}
private T GetMock<T>() where T : class => new Mock<T>().Object;
private object? GetMockOrDefault(Type type)
if (validationExceptions.Any())
throw new AggregateException("Validation failed.", validationExceptions);
}
private void TryResolve(Type type, object?[]? arguments, List<Exception> validationExceptions, bool isFactoryResolve = false)
{
try
{
_iocContainer.TryResolveNonGeneric(type, arguments, null, isFactoryResolve);
}
catch (Exception exception)
{
if (type.IsValueType)
return Activator.CreateInstance(type);
validationExceptions.Add(exception);
}
}
private T GetMock<T>() where T : class => new Mock<T>().Object;
private object? GetMockOrDefault(Type type)
{
if (type.IsValueType)
return Activator.CreateInstance(type);
if (type == typeof(string))
return string.Empty;
if (type == typeof(string))
return string.Empty;
try
{
return GenericMethodCaller.CallPrivate(this, nameof(GetMock), type);
}
catch (Exception)
{
return null;
}
try
{
return GenericMethodCaller.CallPrivate(this, nameof(GetMock), type);
}
catch (Exception)
{
return null;
}
}
}

@ -6,41 +6,40 @@ using System;
using LightweightIocContainer;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class ActionExtensionTest
{
[TestFixture]
public class ActionExtensionTest
private interface IBar
{
private interface IBar
{
void Throw();
}
void Throw();
}
private interface IFoo : IBar
{
private interface IFoo : IBar
{
}
}
private class Foo : IFoo
{
public void Throw() => throw new Exception();
}
private class Foo : IFoo
{
public void Throw() => throw new Exception();
}
[Test]
public void TestConvert()
{
Action<IBar> barAction = bar => bar.Throw();
Action<IFoo> action = barAction.Convert<IFoo, IBar>();
[Test]
public void TestConvert()
{
Action<IBar> barAction = bar => bar.Throw();
Action<IFoo> action = barAction.Convert<IFoo, IBar>();
Assert.Throws<Exception>(() => action(new Foo()));
}
Assert.Throws<Exception>(() => action(new Foo()));
}
[Test]
public void TestConvertActionNull()
{
Action<IBar> barAction = null;
Assert.Null(barAction.Convert<IFoo, IBar>());
}
[Test]
public void TestConvertActionNull()
{
Action<IBar> barAction = null;
Assert.Null(barAction.Convert<IFoo, IBar>());
}
}

@ -14,65 +14,64 @@ using LightweightIocContainer.Interfaces.Registrations;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class AssemblyInstallerTest
{
[TestFixture]
public class AssemblyInstallerTest
[UsedImplicitly]
public class TestInstaller : IIocInstaller
{
[UsedImplicitly]
public class TestInstaller : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<Mock<IRegistration>>();
}
public void Install(IRegistrationCollector registration) => registration.Add<Mock<IRegistration>>();
}
[UsedImplicitly]
public class AssemblyWrapper : Assembly
{
[UsedImplicitly]
public class AssemblyWrapper : Assembly
{
}
}
[Test]
public void TestInstall()
[Test]
public void TestInstall()
{
List<Type> types = new()
{
List<Type> types = new()
{
typeof(object),
typeof(TestInstaller)
};
typeof(object),
typeof(TestInstaller)
};
Mock<AssemblyWrapper> assemblyMock = new();
assemblyMock.Setup(a => a.GetTypes()).Returns(types.ToArray);
Mock<AssemblyWrapper> assemblyMock = new();
assemblyMock.Setup(a => a.GetTypes()).Returns(types.ToArray);
Mock<IRegistrationCollector> registrationCollectorMock = new();
Mock<IRegistrationCollector> registrationCollectorMock = new();
AssemblyInstaller assemblyInstaller = new(assemblyMock.Object);
assemblyInstaller.Install(registrationCollectorMock.Object);
AssemblyInstaller assemblyInstaller = new(assemblyMock.Object);
assemblyInstaller.Install(registrationCollectorMock.Object);
registrationCollectorMock.Verify(r => r.Add<It.IsSubtype<Mock<IRegistration>>>(It.IsAny<Lifestyle>()), Times.Once);
}
registrationCollectorMock.Verify(r => r.Add<It.IsSubtype<Mock<IRegistration>>>(It.IsAny<Lifestyle>()), Times.Once);
}
[Test]
public void TestFromAssemblyThis()
{
IIocContainer iocContainer = new IocContainer();
iocContainer.Install(FromAssembly.This());
}
[Test]
public void TestFromAssemblyThis()
{
IIocContainer iocContainer = new IocContainer();
iocContainer.Install(FromAssembly.This());
}
[Test]
public void TestFromAssemblyInstance()
[Test]
public void TestFromAssemblyInstance()
{
List<Type> types = new()
{
List<Type> types = new()
{
typeof(object),
typeof(TestInstaller)
};
typeof(object),
typeof(TestInstaller)
};
Mock<AssemblyWrapper> assemblyMock = new();
assemblyMock.Setup(a => a.GetTypes()).Returns(types.ToArray);
Mock<AssemblyWrapper> assemblyMock = new();
assemblyMock.Setup(a => a.GetTypes()).Returns(types.ToArray);
IIocContainer iocContainer = new IocContainer();
iocContainer.Install(FromAssembly.Instance(assemblyMock.Object));
}
IIocContainer iocContainer = new IocContainer();
iocContainer.Install(FromAssembly.Instance(assemblyMock.Object));
}
}

@ -9,94 +9,93 @@ using LightweightIocContainer;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class EnumerableExtensionTest
{
[TestFixture]
public class EnumerableExtensionTest
private class ListObject
{
private class ListObject
{
public int Index { get; set; }
}
public int Index { get; set; }
}
private class Given : ListObject
{
private class Given : ListObject
{
}
}
[UsedImplicitly]
public interface ITest
{
void DoSomething();
}
[UsedImplicitly]
public interface ITest
{
void DoSomething();
}
[Test]
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")]
public void TestFirstOrGivenNoPredicateEmpty()
{
List<ListObject> list = new();
Assert.IsInstanceOf<Given>(list.FirstOrGiven<ListObject, Given>());
}
[Test]
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")]
public void TestFirstOrGivenNoPredicateEmpty()
{
List<ListObject> list = new();
Assert.IsInstanceOf<Given>(list.FirstOrGiven<ListObject, Given>());
}
[Test]
public void TestFirstOrGivenNoPredicate()
{
List<ListObject> list = new()
{
new ListObject {Index = 0},
new ListObject {Index = 1},
new ListObject {Index = 2},
new ListObject {Index = 3}
};
ListObject listObject = list.FirstOrGiven<ListObject, Given>();
Assert.IsNotInstanceOf<Given>(listObject);
Assert.AreEqual(0, listObject.Index);
}
[Test]
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")]
public void TestFirstOrGivenPredicateEmpty()
[Test]
public void TestFirstOrGivenNoPredicate()
{
List<ListObject> list = new()
{
List<ListObject> list = new();
Assert.IsInstanceOf<Given>(list.FirstOrGiven<ListObject, Given>(o => o.Index == 2));
}
new ListObject {Index = 0},
new ListObject {Index = 1},
new ListObject {Index = 2},
new ListObject {Index = 3}
};
[Test]
public void TestFirstOrGivenPredicate()
{
List<ListObject> list = new()
{
new ListObject {Index = 0},
new ListObject {Index = 1},
new ListObject {Index = 2},
new ListObject {Index = 3}
};
ListObject listObject = list.FirstOrGiven<ListObject, Given>(o => o.Index == 2);
Assert.IsNotInstanceOf<Given>(listObject);
Assert.AreEqual(2, listObject.Index);
}
[Test]
public void TestForEach()
ListObject listObject = list.FirstOrGiven<ListObject, Given>();
Assert.IsNotInstanceOf<Given>(listObject);
Assert.AreEqual(0, listObject.Index);
}
[Test]
[SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")]
public void TestFirstOrGivenPredicateEmpty()
{
List<ListObject> list = new();
Assert.IsInstanceOf<Given>(list.FirstOrGiven<ListObject, Given>(o => o.Index == 2));
}
[Test]
public void TestFirstOrGivenPredicate()
{
List<ListObject> list = new()
{
Mock<ITest> test1 = new();
Mock<ITest> test2 = new();
Mock<ITest> test3 = new();
Mock<ITest> test4 = new();
new ListObject {Index = 0},
new ListObject {Index = 1},
new ListObject {Index = 2},
new ListObject {Index = 3}
};
ListObject listObject = list.FirstOrGiven<ListObject, Given>(o => o.Index == 2);
Assert.IsNotInstanceOf<Given>(listObject);
Assert.AreEqual(2, listObject.Index);
}
[Test]
public void TestForEach()
{
Mock<ITest> test1 = new();
Mock<ITest> test2 = new();
Mock<ITest> test3 = new();
Mock<ITest> test4 = new();
IEnumerable<ITest> enumerable = new[] { test1.Object, test2.Object, test3.Object, test4.Object };
IEnumerable<ITest> enumerable = new[] { test1.Object, test2.Object, test3.Object, test4.Object };
enumerable.ForEach(t => t.DoSomething());
enumerable.ForEach(t => t.DoSomething());
test1.Verify(t => t.DoSomething(), Times.Once);
test2.Verify(t => t.DoSomething(), Times.Once);
test3.Verify(t => t.DoSomething(), Times.Once);
test4.Verify(t => t.DoSomething(), Times.Once);
}
test1.Verify(t => t.DoSomething(), Times.Once);
test2.Verify(t => t.DoSomething(), Times.Once);
test3.Verify(t => t.DoSomething(), Times.Once);
test4.Verify(t => t.DoSomething(), Times.Once);
}
}

@ -7,267 +7,266 @@ using LightweightIocContainer;
using LightweightIocContainer.Exceptions;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class FluentFactoryRegistrationTest
{
[TestFixture]
public class FluentFactoryRegistrationTest
public interface ITest
{
public interface ITest
{
}
private class Test : ITest
{
}
}
private class TestByte : ITest
{
[UsedImplicitly]
private readonly byte _id;
private class Test : ITest
{
public TestByte(byte id) => _id = id;
}
}
private class TestByte : ITest
{
[UsedImplicitly]
private class TestConstructor : ITest
{
public TestConstructor(string name, Test test)
{
}
public TestConstructor(Test test, string name = null)
{
private readonly byte _id;
}
}
public TestByte(byte id) => _id = id;
}
private interface ITestFactoryNoCreate
[UsedImplicitly]
private class TestConstructor : ITest
{
public TestConstructor(string name, Test test)
{
}
private interface ITestFactoryNonGenericClear
public TestConstructor(Test test, string name = null)
{
ITest Create();
void ClearMultitonInstance();
}
}
[UsedImplicitly]
public interface ITestFactory
{
ITest Create();
ITest Create(string name);
ITest CreateTest(string name = null);
ITest Create(byte id);
}
private interface ITestFactoryNoCreate
{
private class TestFactory : ITestFactory
{
public ITest Create() => new Test();
public ITest Create(string name) => throw new System.NotImplementedException();
public ITest CreateTest(string name = null) => throw new System.NotImplementedException();
public ITest Create(byte id) => throw new System.NotImplementedException();
}
}
[UsedImplicitly]
public interface IMultitonTestFactory
{
ITest Create(MultitonScope scope);
void ClearMultitonInstance<T>();
}
private interface ITestFactoryNonGenericClear
{
ITest Create();
[UsedImplicitly]
public interface IInvalidMultitonTestFactory
{
ITest Create(MultitonScope scope);
ITest Create(int number);
}
void ClearMultitonInstance();
}
[UsedImplicitly]
public interface ITestFactoryWrongReturn
{
public MultitonScope Create();
}
[UsedImplicitly]
public interface ITestFactory
{
ITest Create();
ITest Create(string name);
ITest CreateTest(string name = null);
ITest Create(byte id);
}
public class MultitonScope
{
private class TestFactory : ITestFactory
{
public ITest Create() => new Test();
public ITest Create(string name) => throw new System.NotImplementedException();
public ITest CreateTest(string name = null) => throw new System.NotImplementedException();
public ITest Create(byte id) => throw new System.NotImplementedException();
}
}
[UsedImplicitly]
public interface IMultitonTestFactory
{
ITest Create(MultitonScope scope);
void ClearMultitonInstance<T>();
}
private IocContainer _iocContainer;
[UsedImplicitly]
public interface IInvalidMultitonTestFactory
{
ITest Create(MultitonScope scope);
ITest Create(int number);
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[UsedImplicitly]
public interface ITestFactoryWrongReturn
{
public MultitonScope Create();
}
[TearDown]
public void TearDown() => _iocContainer.Dispose();
public class MultitonScope
{
[Test]
public void TestFluentFactoryRegistration()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
}
ITestFactory factory = _iocContainer.Resolve<ITestFactory>();
ITest test = factory.Create();
ITest test2 = factory.CreateTest();
private IocContainer _iocContainer;
Assert.IsInstanceOf<ITestFactory>(factory);
Assert.IsInstanceOf<ITest>(test);
Assert.IsInstanceOf<ITest>(test2);
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[Test]
public void TestFluentFactoryRegistrationResolveWithoutFactoryFails()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
Assert.Throws<DirectResolveWithRegisteredFactoryNotAllowed>(()=>_iocContainer.Resolve<ITest>());
}
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[Test]
public void TestFluentFactoryRegistration_CustomFactory()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory, TestFactory>());
[Test]
public void TestFluentFactoryRegistration()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
ITestFactory factory = _iocContainer.Resolve<ITestFactory>();
ITest test = factory.Create();
ITestFactory factory = _iocContainer.Resolve<ITestFactory>();
ITest test = factory.Create();
ITest test2 = factory.CreateTest();
Assert.IsInstanceOf<ITestFactory>(factory);
Assert.IsInstanceOf<ITest>(test);
}
Assert.IsInstanceOf<ITestFactory>(factory);
Assert.IsInstanceOf<ITest>(test);
Assert.IsInstanceOf<ITest>(test2);
}
[Test]
public void TestFluentFactoryRegistration_WithoutFactoryFails()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory, TestFactory>());
Assert.Throws<DirectResolveWithRegisteredFactoryNotAllowed>(()=>_iocContainer.Resolve<ITest>());
}
[Test]
public void TestFluentFactoryRegistrationResolveWithoutFactoryFails()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
Assert.Throws<DirectResolveWithRegisteredFactoryNotAllowed>(()=>_iocContainer.Resolve<ITest>());
}
[Test]
public void TestFluentFactoryRegistration_CustomFactory()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory, TestFactory>());
[Test]
public void TestRegisterFactoryWithoutCreate() => Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryNoCreate>()));
ITestFactory factory = _iocContainer.Resolve<ITestFactory>();
ITest test = factory.Create();
[Test]
public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws<IllegalAbstractMethodCreationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryNonGenericClear>()));
Assert.IsInstanceOf<ITestFactory>(factory);
Assert.IsInstanceOf<ITest>(test);
}
[Test]
public void TestResolveFromFactory()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
[Test]
public void TestFluentFactoryRegistration_WithoutFactoryFails()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory, TestFactory>());
Assert.Throws<DirectResolveWithRegisteredFactoryNotAllowed>(()=>_iocContainer.Resolve<ITest>());
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
Assert.IsInstanceOf<Test>(createdTest);
}
[Test]
public void TestRegisterFactoryWithoutCreate() => Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryNoCreate>()));
[Test]
public void TestResolveFromFactoryWithParams()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
[Test]
public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws<IllegalAbstractMethodCreationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryNonGenericClear>()));
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create("Test");
[Test]
public void TestResolveFromFactory()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactory>());
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
[Test]
public void TestResolveFromFactoryWithDefaultParamCreate()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
Assert.IsInstanceOf<Test>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.CreateTest();
[Test]
public void TestResolveFromFactoryWithParams()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create("Test");
[Test]
public void TestResolveFromFactoryWithDefaultParamCtor()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
[Test]
public void TestResolveFromFactoryWithDefaultParamCreate()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.CreateTest();
[Test]
public void TestResolveFromFactoryWithByte()
{
_iocContainer.Register(r => r.Add<ITest, TestByte>().WithFactory<ITestFactory>());
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create(1);
[Test]
public void TestResolveFromFactoryWithDefaultParamCtor()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>().WithFactory<ITestFactory>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
Assert.IsInstanceOf<TestByte>(createdTest);
}
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create();
[Test]
public void TestResolveMultitonFromFactory()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IMultitonTestFactory>());
Assert.IsInstanceOf<TestConstructor>(createdTest);
}
MultitonScope scope1 = new();
MultitonScope scope2 = new();
[Test]
public void TestResolveFromFactoryWithByte()
{
_iocContainer.Register(r => r.Add<ITest, TestByte>().WithFactory<ITestFactory>());
IMultitonTestFactory testFactory = _iocContainer.Resolve<IMultitonTestFactory>();
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest createdTest = testFactory.Create(1);
ITest resolvedTest1 = testFactory.Create(scope1);
ITest resolvedTest2 = testFactory.Create(scope1);
ITest resolvedTest3 = testFactory.Create(scope2);
Assert.IsInstanceOf<TestByte>(createdTest);
}
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
}
[Test]
public void TestResolveMultitonFromFactory()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IMultitonTestFactory>());
[Test]
public void TestResolveMultitonFromFactoryClearInstances()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IMultitonTestFactory>());
MultitonScope scope1 = new();
MultitonScope scope2 = new();
IMultitonTestFactory testFactory = _iocContainer.Resolve<IMultitonTestFactory>();
MultitonScope scope1 = new();
MultitonScope scope2 = new();
ITest resolvedTest1 = testFactory.Create(scope1);
ITest resolvedTest2 = testFactory.Create(scope1);
ITest resolvedTest3 = testFactory.Create(scope2);
IMultitonTestFactory testFactory = _iocContainer.Resolve<IMultitonTestFactory>();
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
}
ITest resolvedTest1 = testFactory.Create(scope1);
ITest resolvedTest2 = testFactory.Create(scope1);
ITest resolvedTest3 = testFactory.Create(scope2);
[Test]
public void TestResolveMultitonFromFactoryClearInstances()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IMultitonTestFactory>());
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
MultitonScope scope1 = new();
MultitonScope scope2 = new();
testFactory.ClearMultitonInstance<ITest>();
IMultitonTestFactory testFactory = _iocContainer.Resolve<IMultitonTestFactory>();
ITest resolvedTest4 = testFactory.Create(scope1);
ITest resolvedTest5 = testFactory.Create(scope2);
ITest resolvedTest1 = testFactory.Create(scope1);
ITest resolvedTest2 = testFactory.Create(scope1);
ITest resolvedTest3 = testFactory.Create(scope2);
Assert.AreNotSame(resolvedTest1, resolvedTest4);
Assert.AreNotSame(resolvedTest2, resolvedTest4);
Assert.AreNotSame(resolvedTest3, resolvedTest5);
}
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
[Test]
public void InvalidMultitonFactoryRegistrationFactoryWithoutParameter() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<ITestFactory>()));
testFactory.ClearMultitonInstance<ITest>();
[Test]
public void InvalidMultitonFactoryRegistrationFactoryWithoutScopeAsFirstParameter() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IInvalidMultitonTestFactory>()));
ITest resolvedTest4 = testFactory.Create(scope1);
ITest resolvedTest5 = testFactory.Create(scope2);
[Test]
public void TestInvalidCreateMethodReturnType() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryWrongReturn>()));
Assert.AreNotSame(resolvedTest1, resolvedTest4);
Assert.AreNotSame(resolvedTest2, resolvedTest4);
Assert.AreNotSame(resolvedTest3, resolvedTest5);
}
[Test]
public void InvalidMultitonFactoryRegistrationFactoryWithoutParameter() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<ITestFactory>()));
[Test]
public void InvalidMultitonFactoryRegistrationFactoryWithoutScopeAsFirstParameter() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>().WithFactory<IInvalidMultitonTestFactory>()));
[Test]
public void TestInvalidCreateMethodReturnType() =>
Assert.Throws<InvalidFactoryRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithFactory<ITestFactoryWrongReturn>()));
}

@ -7,158 +7,157 @@ using JetBrains.Annotations;
using LightweightIocContainer;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class IocContainerInterfaceSegregationTest
{
[TestFixture]
public class IocContainerInterfaceSegregationTest
private interface IBar
{
}
private interface IFoo
{
void ThrowFoo();
}
private interface IAnotherBar
{
}
private interface IAnotherFoo
{
}
private interface IAnotherOne
{
}
[UsedImplicitly]
private class Foo : IFoo, IBar, IAnotherFoo, IAnotherBar, IAnotherOne
{
public void ThrowFoo() => throw new Exception("Foo");
}
private IocContainer _container;
[SetUp]
public void SetUp() => _container = new IocContainer();
[TearDown]
public void TearDown() => _container.Dispose();
[Test]
public void TestRegistrationOnCreate2()
{
_container.Register(r => r.Add<IBar, IFoo, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
}
[Test]
public void TestRegistrationOnCreate3()
{
private interface IBar
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, Foo>().OnCreate(foo => foo.ThrowFoo()));
}
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
private interface IFoo
{
void ThrowFoo();
}
private interface IAnotherBar
{
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
}
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
}
private interface IAnotherFoo
{
[Test]
public void TestRegistrationOnCreate4()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, Foo>().OnCreate(foo => foo.ThrowFoo()));
}
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
private interface IAnotherOne
{
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
}
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
Exception anotherBarException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherBar>());
Assert.AreEqual("Foo", anotherBarException?.Message);
}
[UsedImplicitly]
private class Foo : IFoo, IBar, IAnotherFoo, IAnotherBar, IAnotherOne
{
public void ThrowFoo() => throw new Exception("Foo");
}
[Test]
public void TestRegistrationOnCreate5()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
private IocContainer _container;
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
[SetUp]
public void SetUp() => _container = new IocContainer();
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
[TearDown]
public void TearDown() => _container.Dispose();
Exception anotherBarException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherBar>());
Assert.AreEqual("Foo", anotherBarException?.Message);
[Test]
public void TestRegistrationOnCreate2()
{
_container.Register(r => r.Add<IBar, IFoo, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception anotherOneException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherOne>());
Assert.AreEqual("Foo", anotherOneException?.Message);
}
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
[Test]
public void TestResolveTransient()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>());
IFoo foo = _container.Resolve<IFoo>();
IBar bar = _container.Resolve<IBar>();
IAnotherFoo anotherFoo = _container.Resolve<IAnotherFoo>();
IAnotherBar anotherBar = _container.Resolve<IAnotherBar>();
IAnotherOne anotherOne = _container.Resolve<IAnotherOne>();
Assert.IsInstanceOf<Foo>(foo);
Assert.IsInstanceOf<Foo>(bar);
Assert.IsInstanceOf<Foo>(anotherFoo);
Assert.IsInstanceOf<Foo>(anotherBar);
Assert.IsInstanceOf<Foo>(anotherOne);
}
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
}
[Test]
public void TestRegistrationOnCreate3()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
}
[Test]
public void TestRegistrationOnCreate4()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
Exception anotherBarException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherBar>());
Assert.AreEqual("Foo", anotherBarException?.Message);
}
[Test]
public void TestRegistrationOnCreate5()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>().OnCreate(foo => foo.ThrowFoo()));
Exception fooException = Assert.Throws<Exception>(() => _container.Resolve<IFoo>());
Assert.AreEqual("Foo", fooException?.Message);
Exception barException = Assert.Throws<Exception>(() => _container.Resolve<IBar>());
Assert.AreEqual("Foo", barException?.Message);
Exception anotherFooException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherFoo>());
Assert.AreEqual("Foo", anotherFooException?.Message);
Exception anotherBarException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherBar>());
Assert.AreEqual("Foo", anotherBarException?.Message);
Exception anotherOneException = Assert.Throws<Exception>(() => _container.Resolve<IAnotherOne>());
Assert.AreEqual("Foo", anotherOneException?.Message);
}
[Test]
public void TestResolveTransient()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>());
IFoo foo = _container.Resolve<IFoo>();
IBar bar = _container.Resolve<IBar>();
IAnotherFoo anotherFoo = _container.Resolve<IAnotherFoo>();
IAnotherBar anotherBar = _container.Resolve<IAnotherBar>();
IAnotherOne anotherOne = _container.Resolve<IAnotherOne>();
Assert.IsInstanceOf<Foo>(foo);
Assert.IsInstanceOf<Foo>(bar);
Assert.IsInstanceOf<Foo>(anotherFoo);
Assert.IsInstanceOf<Foo>(anotherBar);
Assert.IsInstanceOf<Foo>(anotherOne);
}
[Test]
public void TestResolveSingleton()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>(Lifestyle.Singleton));
IFoo foo = _container.Resolve<IFoo>();
IBar bar = _container.Resolve<IBar>();
IAnotherFoo anotherFoo = _container.Resolve<IAnotherFoo>();
IAnotherBar anotherBar = _container.Resolve<IAnotherBar>();
IAnotherOne anotherOne = _container.Resolve<IAnotherOne>();
Assert.IsInstanceOf<Foo>(foo);
Assert.IsInstanceOf<Foo>(bar);
Assert.IsInstanceOf<Foo>(anotherFoo);
Assert.IsInstanceOf<Foo>(anotherBar);
Assert.IsInstanceOf<Foo>(anotherOne);
Assert.AreEqual(foo, bar);
Assert.AreEqual(foo, anotherFoo);
Assert.AreEqual(foo, anotherBar);
Assert.AreEqual(foo, anotherOne);
Assert.AreSame(foo, bar);
Assert.AreSame(foo, anotherFoo);
Assert.AreSame(foo, anotherBar);
Assert.AreSame(foo, anotherOne);
}
[Test]
public void TestResolveSingleton()
{
_container.Register(r => r.Add<IBar, IFoo, IAnotherFoo, IAnotherBar, IAnotherOne, Foo>(Lifestyle.Singleton));
IFoo foo = _container.Resolve<IFoo>();
IBar bar = _container.Resolve<IBar>();
IAnotherFoo anotherFoo = _container.Resolve<IAnotherFoo>();
IAnotherBar anotherBar = _container.Resolve<IAnotherBar>();
IAnotherOne anotherOne = _container.Resolve<IAnotherOne>();
Assert.IsInstanceOf<Foo>(foo);
Assert.IsInstanceOf<Foo>(bar);
Assert.IsInstanceOf<Foo>(anotherFoo);
Assert.IsInstanceOf<Foo>(anotherBar);
Assert.IsInstanceOf<Foo>(anotherOne);
Assert.AreEqual(foo, bar);
Assert.AreEqual(foo, anotherFoo);
Assert.AreEqual(foo, anotherBar);
Assert.AreEqual(foo, anotherOne);
Assert.AreSame(foo, bar);
Assert.AreSame(foo, anotherFoo);
Assert.AreSame(foo, anotherBar);
Assert.AreSame(foo, anotherOne);
}
}

@ -6,154 +6,153 @@ using JetBrains.Annotations;
using LightweightIocContainer;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
// ReSharper disable MemberHidesStaticFromOuterClass
public class IocContainerParameterRegistrationTest
{
[TestFixture]
// ReSharper disable MemberHidesStaticFromOuterClass
public class IocContainerParameterRegistrationTest
[UsedImplicitly]
public interface IA
{
[UsedImplicitly]
public interface IA
{
IB B { get; }
IC C { get; }
}
IB B { get; }
IC C { get; }
}
[UsedImplicitly]
public interface IB
{
[UsedImplicitly]
public interface IB
{
}
}
[UsedImplicitly]
public interface IC
{
[UsedImplicitly]
public interface IC
{
}
}
[UsedImplicitly]
public interface ID
{
IA A { get; }
IA A2 { get; }
IB B { get; }
IC C { get; }
}
[UsedImplicitly]
public interface ID
{
IA A { get; }
IA A2 { get; }
IB B { get; }
IC C { get; }
}
[UsedImplicitly]
private class A : IA
[UsedImplicitly]
private class A : IA
{
public A(IB b, IC c)
{
public A(IB b, IC c)
{
B = b;
C = c;
}
public IB B { get; }
public IC C { get; }
B = b;
C = c;
}
[UsedImplicitly]
private class B : IB
public IB B { get; }
public IC C { get; }
}
[UsedImplicitly]
private class B : IB
{
public B(IC c)
{
public B(IC c)
{
}
}
}
[UsedImplicitly]
private class C : IC
{
[UsedImplicitly]
private class C : IC
{
}
}
[UsedImplicitly]
private class D : ID
[UsedImplicitly]
private class D : ID
{
public D(IA a, IA a2, IB b, IC c)
{
public D(IA a, IA a2, IB b, IC c)
{
A = a;
A2 = a2;
B = b;
C = c;
}
public IA A { get; }
public IA A2 { get; }
public IB B { get; }
public IC C { get; }
A = a;
A2 = a2;
B = b;
C = c;
}
public IA A { get; }
public IA A2 { get; }
public IB B { get; }
public IC C { get; }
}
private IocContainer _iocContainer;
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
private IocContainer _iocContainer;
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[Test]
public void TestResolveOnlyRegistrationParameters()
{
IC c = new C();
IB b = new B(c);
_iocContainer.Register(r => r.Add<IA, A>().WithParameters(b, c));
IA a = _iocContainer.Resolve<IA>();
[Test]
public void TestResolveOnlyRegistrationParameters()
{
IC c = new C();
IB b = new B(c);
Assert.AreEqual(b, a.B);
Assert.AreEqual(c, a.C);
}
_iocContainer.Register(r => r.Add<IA, A>().WithParameters(b, c));
IA a = _iocContainer.Resolve<IA>();
[Test]
public void TestResolveRegistrationAndResolveParameters()
{
IC c = new C();
IB b = new B(c);
Assert.AreEqual(b, a.B);
Assert.AreEqual(c, a.C);
}
_iocContainer.Register(r => r.Add<IA, A>().WithParameters(b));
IA a = _iocContainer.Resolve<IA>(c);
[Test]
public void TestResolveRegistrationAndResolveParameters()
{
IC c = new C();
IB b = new B(c);
Assert.AreEqual(b, a.B);
Assert.AreEqual(c, a.C);
}
_iocContainer.Register(r => r.Add<IA, A>().WithParameters(b));
IA a = _iocContainer.Resolve<IA>(c);
[Test]
public void TestResolveRegistrationAndResolveParametersMixedOrder()
{
IC c = new C();
IB b = new B(c);
IA a = new A(b, c);
IA a2 = new A(b, c);
_iocContainer.Register(r => r.Add<ID, D>().WithParameters((0, a), (2, b), (3, c)));
ID d = _iocContainer.Resolve<ID>(a2);
Assert.AreEqual(a, d.A);
Assert.AreEqual(a2, d.A2);
Assert.AreEqual(b, d.B);
Assert.AreEqual(c, d.C);
}
Assert.AreEqual(b, a.B);
Assert.AreEqual(c, a.C);
}
[Test]
public void TestResolveRegistrationParametersAndResolvedParameters()
{
IC c = new C();
IB b = new B(c);
IA a = new A(b, c);
IA a2 = new A(b, c);
[Test]
public void TestResolveRegistrationAndResolveParametersMixedOrder()
{
IC c = new C();
IB b = new B(c);
IA a = new A(b, c);
IA a2 = new A(b, c);
_iocContainer.Register(r => r.Add<ID, D>().WithParameters((0, a), (2, b), (3, c)));
ID d = _iocContainer.Resolve<ID>(a2);
Assert.AreEqual(a, d.A);
Assert.AreEqual(a2, d.A2);
Assert.AreEqual(b, d.B);
Assert.AreEqual(c, d.C);
}
_iocContainer.Register(r => r.Add<ID, D>().WithParameters(a2));
_iocContainer.Register(r => r.Add<IB, B>());
_iocContainer.Register(r => r.Add<IC, C>());
[Test]
public void TestResolveRegistrationParametersAndResolvedParameters()
{
IC c = new C();
IB b = new B(c);
IA a = new A(b, c);
IA a2 = new A(b, c);
ID d = _iocContainer.Resolve<ID>(a);
_iocContainer.Register(r => r.Add<ID, D>().WithParameters(a2));
_iocContainer.Register(r => r.Add<IB, B>());
_iocContainer.Register(r => r.Add<IC, C>());
Assert.AreEqual(a, d.A2);
Assert.AreEqual(a2, d.A);
}
ID d = _iocContainer.Resolve<ID>(a);
Assert.AreEqual(a, d.A2);
Assert.AreEqual(a2, d.A);
}
}

@ -9,158 +9,157 @@ using LightweightIocContainer.Exceptions;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class IocContainerRecursionTest
{
[TestFixture]
public class IocContainerRecursionTest
[UsedImplicitly]
public interface IFoo
{
[UsedImplicitly]
public interface IFoo
{
}
}
[UsedImplicitly]
public interface IBar
{
[UsedImplicitly]
public interface IBar
{
}
}
[UsedImplicitly]
private class Foo : IFoo
[UsedImplicitly]
private class Foo : IFoo
{
public Foo(IBar bar)
{
public Foo(IBar bar)
{
}
}
}
[UsedImplicitly]
private class Bar : IBar
[UsedImplicitly]
private class Bar : IBar
{
public Bar(IFoo foo)
{
public Bar(IFoo foo)
{
}
}
}
[UsedImplicitly]
public interface IA
{
[UsedImplicitly]
public interface IA
{
}
}
[UsedImplicitly]
public interface IB
{
[UsedImplicitly]
public interface IB
{
}
}
[UsedImplicitly]
public interface IC
{
[UsedImplicitly]
public interface IC
{
}
}
[UsedImplicitly]
private class A : IA
[UsedImplicitly]
private class A : IA
{
public A(IB b, IC c)
{
public A(IB b, IC c)
{
}
}
}
[UsedImplicitly]
private class B : IB
[UsedImplicitly]
private class B : IB
{
public B(IC c)
{
public B(IC c)
{
}
}
}
[UsedImplicitly]
private class C : IC
{
[UsedImplicitly]
private class C : IC
{
}
}
[UsedImplicitly]
private class ATwoCtor : IA
{
public ATwoCtor(IB b) => Console.WriteLine("A with args");
public ATwoCtor() => Console.WriteLine("A without args");
}
[UsedImplicitly]
private class ATwoCtor : IA
{
public ATwoCtor(IB b) => Console.WriteLine("A with args");
public ATwoCtor() => Console.WriteLine("A without args");
}
[UsedImplicitly]
private class BTwoCtor : IB
{
public BTwoCtor(IA a) => Console.WriteLine("B with args");
public BTwoCtor() => Console.WriteLine("B without args");
}
[UsedImplicitly]
private class BTwoCtor : IB
{
public BTwoCtor(IA a) => Console.WriteLine("B with args");
public BTwoCtor() => Console.WriteLine("B without args");
}
private IocContainer _iocContainer;
private IocContainer _iocContainer;
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[Test]
public void TestCircularDependencies()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<IBar, Bar>());
[Test]
public void TestCircularDependencies()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<IBar, Bar>());
NoMatchingConstructorFoundException noMatchingConstructorFoundException = Assert.Throws<NoMatchingConstructorFoundException>(() => _iocContainer.Resolve<IFoo>());
ConstructorNotMatchingException fooConstructorNotMatchingException = (ConstructorNotMatchingException) noMatchingConstructorFoundException?.InnerExceptions[0];
NoMatchingConstructorFoundException noMatchingBarConstructorFoundException = (NoMatchingConstructorFoundException) fooConstructorNotMatchingException?.InnerExceptions[0];
ConstructorNotMatchingException barConstructorNotMatchingException = (ConstructorNotMatchingException) noMatchingBarConstructorFoundException?.InnerExceptions[0];
NoMatchingConstructorFoundException noMatchingConstructorFoundException = Assert.Throws<NoMatchingConstructorFoundException>(() => _iocContainer.Resolve<IFoo>());
ConstructorNotMatchingException fooConstructorNotMatchingException = (ConstructorNotMatchingException) noMatchingConstructorFoundException?.InnerExceptions[0];
NoMatchingConstructorFoundException noMatchingBarConstructorFoundException = (NoMatchingConstructorFoundException) fooConstructorNotMatchingException?.InnerExceptions[0];
ConstructorNotMatchingException barConstructorNotMatchingException = (ConstructorNotMatchingException) noMatchingBarConstructorFoundException?.InnerExceptions[0];
CircularDependencyException exception = (CircularDependencyException) barConstructorNotMatchingException?.InnerExceptions[0];
CircularDependencyException exception = (CircularDependencyException) barConstructorNotMatchingException?.InnerExceptions[0];
Assert.AreEqual(typeof(IFoo), exception?.ResolvingType);
Assert.AreEqual(2, exception.ResolveStack.Count);
Assert.AreEqual(typeof(IFoo), exception?.ResolvingType);
Assert.AreEqual(2, exception.ResolveStack.Count);
string message = $"Circular dependency has been detected when trying to resolve `{typeof(IFoo)}`.\n" +
"Resolve stack that resulted in the circular dependency:\n" +
$"\t`{typeof(IFoo)}` resolved as dependency of\n" +
$"\t`{typeof(IBar)}` resolved as dependency of\n" +
$"\t`{typeof(IFoo)}` which is the root type being resolved.";
string message = $"Circular dependency has been detected when trying to resolve `{typeof(IFoo)}`.\n" +
"Resolve stack that resulted in the circular dependency:\n" +
$"\t`{typeof(IFoo)}` resolved as dependency of\n" +
$"\t`{typeof(IBar)}` resolved as dependency of\n" +
$"\t`{typeof(IFoo)}` which is the root type being resolved.";
Assert.AreEqual(message, exception.Message);
}
Assert.AreEqual(message, exception.Message);
}
[Test]
public void TestNonCircularDependencies()
{
_iocContainer.Register(r => r.Add<IA, A>());
_iocContainer.Register(r => r.Add<IB, B>());
_iocContainer.Register(r => r.Add<IC, C>());
[Test]
public void TestNonCircularDependencies()
{
_iocContainer.Register(r => r.Add<IA, A>());
_iocContainer.Register(r => r.Add<IB, B>());
_iocContainer.Register(r => r.Add<IC, C>());
IA a = _iocContainer.Resolve<IA>();
Assert.IsNotNull(a);
}
IA a = _iocContainer.Resolve<IA>();
Assert.IsNotNull(a);
}
[Test]
public void TestRecursionWithParam()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<IBar, Bar>());
[Test]
public void TestRecursionWithParam()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<IBar, Bar>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<IFoo>(new Mock<IBar>().Object));
Assert.DoesNotThrow(() => _iocContainer.Resolve<IBar>(new Mock<IFoo>().Object));
}
Assert.DoesNotThrow(() => _iocContainer.Resolve<IFoo>(new Mock<IBar>().Object));
Assert.DoesNotThrow(() => _iocContainer.Resolve<IBar>(new Mock<IFoo>().Object));
}
[Test]
public void TestNonCircularCrossDependencies()
{
_iocContainer.Register(r => r.Add<IA, ATwoCtor>());
_iocContainer.Register(r => r.Add<IB, BTwoCtor>());
[Test]
public void TestNonCircularCrossDependencies()
{
_iocContainer.Register(r => r.Add<IA, ATwoCtor>());
_iocContainer.Register(r => r.Add<IB, BTwoCtor>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<IA>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<IB>());
}
Assert.DoesNotThrow(() => _iocContainer.Resolve<IA>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<IB>());
}
}

@ -7,356 +7,355 @@ using LightweightIocContainer.Interfaces.Registrations;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class IocContainerTest
{
[TestFixture]
public class IocContainerTest
private interface ITest
{
private interface ITest
{
}
}
private interface IFoo
{
private interface IFoo
{
}
}
private class Test : ITest
{
private class Test : ITest
{
}
}
[UsedImplicitly]
private class TestConstructor : ITest
[UsedImplicitly]
private class TestConstructor : ITest
{
public TestConstructor(string name, Test test)
{
public TestConstructor(string name, Test test)
{
}
public TestConstructor(Test test, string name = null)
{
}
public TestConstructor(IFoo foo, string name)
{
}
}
[UsedImplicitly]
private class TestPrivateConstructor : ITest
public TestConstructor(Test test, string name = null)
{
private TestPrivateConstructor()
{
}
}
[UsedImplicitly]
private class TestMultipleConstructors : ITest
public TestConstructor(IFoo foo, string name)
{
public TestMultipleConstructors(string name, bool success)
{
}
public TestMultipleConstructors(string name)
{
}
}
}
[UsedImplicitly]
private class TestWithFoo : ITest
[UsedImplicitly]
private class TestPrivateConstructor : ITest
{
private TestPrivateConstructor()
{
public TestWithFoo(IFoo testFoo) => TestFoo = testFoo;
public IFoo TestFoo { get; }
}
}
[UsedImplicitly]
private class Foo : IFoo
[UsedImplicitly]
private class TestMultipleConstructors : ITest
{
public TestMultipleConstructors(string name, bool success)
{
}
[UsedImplicitly]
private class FooConstructor : IFoo
public TestMultipleConstructors(string name)
{
public FooConstructor(string test)
{
}
}
}
private class MultitonScope
[UsedImplicitly]
private class TestWithFoo : ITest
{
public TestWithFoo(IFoo testFoo) => TestFoo = testFoo;
public IFoo TestFoo { get; }
}
[UsedImplicitly]
private class Foo : IFoo
{
}
[UsedImplicitly]
private class FooConstructor : IFoo
{
public FooConstructor(string test)
{
}
}
private class MultitonScope
{
private IocContainer _iocContainer;
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
private IocContainer _iocContainer;
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[Test]
public void TestInstall()
{
Mock<IIocInstaller> installerMock = new();
IIocContainer returnedContainer = _iocContainer.Install(installerMock.Object);
[TearDown]
public void TearDown() => _iocContainer.Dispose();
installerMock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
Assert.AreEqual(_iocContainer, returnedContainer);
}
[Test]
public void TestInstall()
{
Mock<IIocInstaller> installerMock = new();
IIocContainer returnedContainer = _iocContainer.Install(installerMock.Object);
[Test]
public void TestInstallMultiple()
{
Mock<IIocInstaller> installer1Mock = new();
Mock<IIocInstaller> installer2Mock = new();
Mock<IIocInstaller> installer3Mock = new();
installerMock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
IIocContainer returnedContainer = _iocContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object);
Assert.AreEqual(_iocContainer, returnedContainer);
}
installer1Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
installer2Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
installer3Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
[Test]
public void TestInstallMultiple()
{
Mock<IIocInstaller> installer1Mock = new();
Mock<IIocInstaller> installer2Mock = new();
Mock<IIocInstaller> installer3Mock = new();
Assert.AreEqual(_iocContainer, returnedContainer);
}
IIocContainer returnedContainer = _iocContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object);
[Test]
public void TestRegister() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>()));
installer1Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
installer2Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
installer3Mock.Verify(m => m.Install(It.IsAny<IRegistrationCollector>()), Times.Once);
[Test]
public void TestRegisterTypeWithoutInterface() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<Test>()));
Assert.AreEqual(_iocContainer, returnedContainer);
}
[Test]
public void TestRegisterMultiton() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>()));
[Test]
public void TestRegister() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>()));
[Test]
public void TestInvalidMultitonRegistration() => Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Multiton)));
[Test]
public void TestRegisterTypeWithoutInterface() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<Test>()));
[Test]
public void TestRegisterMultipleDifferent()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, TestConstructor>()));
Assert.AreEqual(typeof(ITest), exception?.Type);
}
[Test]
public void TestRegisterMultiton() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>()));
[Test]
public void TestRegisterMultipleSame()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>()));
}
[Test]
public void TestInvalidMultitonRegistration() => Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Multiton)));
[Test]
public void TestRegisterMultipleSameWithParameters()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithParameters("test", 1, new Foo()));
Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithParameters("test", 1, new Foo())));
}
[Test]
public void TestRegisterMultipleDifferent()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, TestConstructor>()));
Assert.AreEqual(typeof(ITest), exception?.Type);
}
[Test]
public void TestResolveNotRegistered()
{
TypeNotRegisteredException exception = Assert.Throws<TypeNotRegisteredException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception?.Type);
}
[Test]
public void TestRegisterMultipleSame()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>()));
}
[Test]
public void TestResolve()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
[Test]
public void TestRegisterMultipleSameWithParameters()
{
_iocContainer.Register(r => r.Add<ITest, Test>().WithParameters("test", 1, new Foo()));
Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add<ITest, Test>().WithParameters("test", 1, new Foo())));
}
ITest resolvedTest = _iocContainer.Resolve<ITest>();
[Test]
public void TestResolveNotRegistered()
{
TypeNotRegisteredException exception = Assert.Throws<TypeNotRegisteredException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception?.Type);
}
Assert.IsInstanceOf<Test>(resolvedTest);
}
[Test]
public void TestResolve()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
[Test]
public void TestResolveWithoutInterface()
{
_iocContainer.Register(r => r.Add<Test>());
ITest resolvedTest = _iocContainer.Resolve<ITest>();
Test resolvedTest = _iocContainer.Resolve<Test>();
Assert.IsInstanceOf<Test>(resolvedTest);
}
Assert.IsInstanceOf<Test>(resolvedTest);
}
[Test]
public void TestResolveWithoutInterface()
{
_iocContainer.Register(r => r.Add<Test>());
[Test]
public void TestResolveInterfaceWithoutImplementation()
{
_iocContainer.Register(r => r.Add<ITest>());
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Resolve<ITest>());
}
Test resolvedTest = _iocContainer.Resolve<Test>();
[Test]
public void TestResolveImplementationRegisteredWithInterface()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
Assert.IsInstanceOf<Test>(resolvedTest);
}
Test resolvedTest = _iocContainer.Resolve<Test>();
[Test]
public void TestResolveInterfaceWithoutImplementation()
{
_iocContainer.Register(r => r.Add<ITest>());
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Resolve<ITest>());
}
Assert.IsInstanceOf<Test>(resolvedTest);
}
[Test]
public void TestResolveImplementationRegisteredWithInterface()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
[Test]
public void TestResolveWithParams()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
Test resolvedTest = _iocContainer.Resolve<Test>();
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test", new Test());
Assert.IsInstanceOf<Test>(resolvedTest);
}
Assert.IsInstanceOf<TestConstructor>(resolvedTest);
}
[Test]
public void TestResolveWithParams()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
[Test]
public void TestResolveWithMissingParam()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test", new Test());
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test");
Assert.IsInstanceOf<TestConstructor>(resolvedTest);
}
Assert.IsInstanceOf<TestConstructor>(resolvedTest);
}
[Test]
public void TestResolveWithMissingParam()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
_iocContainer.Register(r => r.Add<Test, Test>()); //this registration is abnormal and should only be used in unit tests
[Test]
public void TestResolveSingleton()
{
_iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Singleton));
ITest resolvedTest = _iocContainer.Resolve<ITest>("Test");
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
Assert.IsInstanceOf<TestConstructor>(resolvedTest);
}
Assert.AreEqual(resolvedTest, secondResolvedTest);
}
[Test]
public void TestResolveSingleton()
{
_iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Singleton));
[Test]
public void TestResolveMultiton()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
MultitonScope scope1 = new();
MultitonScope scope2 = new();
Assert.AreEqual(resolvedTest, secondResolvedTest);
}
ITest resolvedTest1 = _iocContainer.Resolve<ITest>(scope1);
ITest resolvedTest2 = _iocContainer.Resolve<ITest>(scope1);
ITest resolvedTest3 = _iocContainer.Resolve<ITest>(scope2);
[Test]
public void TestResolveMultiton()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
}
MultitonScope scope1 = new();
MultitonScope scope2 = new();
[Test]
public void TestResolveMultitonNoArgs()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
ITest resolvedTest1 = _iocContainer.Resolve<ITest>(scope1);
ITest resolvedTest2 = _iocContainer.Resolve<ITest>(scope1);
ITest resolvedTest3 = _iocContainer.Resolve<ITest>(scope2);
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception?.Type);
}
Assert.AreSame(resolvedTest1, resolvedTest2);
Assert.AreNotSame(resolvedTest1, resolvedTest3);
Assert.AreNotSame(resolvedTest2, resolvedTest3);
}
[Test]
public void TestResolveMultitonWrongArgs()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
[Test]
public void TestResolveMultitonNoArgs()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>(new object()));
Assert.AreEqual(typeof(ITest), exception?.Type);
}
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(ITest), exception?.Type);
}
[Test]
public void TestResolveTransient()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
[Test]
public void TestResolveMultitonWrongArgs()
{
_iocContainer.Register(r => r.AddMultiton<ITest, Test, MultitonScope>());
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
MultitonResolveException exception = Assert.Throws<MultitonResolveException>(() => _iocContainer.Resolve<ITest>(new object()));
Assert.AreEqual(typeof(ITest), exception?.Type);
}
Assert.AreNotEqual(resolvedTest, secondResolvedTest);
}
[Test]
public void TestResolveTransient()
{
_iocContainer.Register(r => r.Add<ITest, Test>());
[Test]
public void TestResolveNoMatchingConstructor()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
NoMatchingConstructorFoundException exception = Assert.Throws<NoMatchingConstructorFoundException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(TestConstructor), exception?.Type);
}
ITest resolvedTest = _iocContainer.Resolve<ITest>();
ITest secondResolvedTest = _iocContainer.Resolve<ITest>();
[Test]
public void TestResolveNoMatchingConstructorNotThrownWrongly()
{
_iocContainer.Register(r => r.Add<ITest, TestMultipleConstructors>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<ITest>("Name"));
}
Assert.AreNotEqual(resolvedTest, secondResolvedTest);
}
[Test]
public void TestResolvePrivateConstructor()
{
_iocContainer.Register(r => r.Add<ITest, TestPrivateConstructor>());
NoPublicConstructorFoundException exception = Assert.Throws<NoPublicConstructorFoundException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(TestPrivateConstructor), exception?.Type);
}
[Test]
public void TestResolveNoMatchingConstructor()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
NoMatchingConstructorFoundException exception = Assert.Throws<NoMatchingConstructorFoundException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(TestConstructor), exception?.Type);
}
[Test]
public void TestResolveSingleTypeRegistrationWithFactoryMethod()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<ITest>().WithFactoryMethod(c => new TestConstructor(c.Resolve<IFoo>(), "someName")));
[Test]
public void TestResolveNoMatchingConstructorNotThrownWrongly()
{
_iocContainer.Register(r => r.Add<ITest, TestMultipleConstructors>());
Assert.DoesNotThrow(() => _iocContainer.Resolve<ITest>("Name"));
}
ITest test = _iocContainer.Resolve<ITest>();
[Test]
public void TestResolvePrivateConstructor()
{
_iocContainer.Register(r => r.Add<ITest, TestPrivateConstructor>());
NoPublicConstructorFoundException exception = Assert.Throws<NoPublicConstructorFoundException>(() => _iocContainer.Resolve<ITest>());
Assert.AreEqual(typeof(TestPrivateConstructor), exception?.Type);
}
Assert.NotNull(test);
}
[Test]
public void TestResolveSingleTypeRegistrationWithFactoryMethod()
{
_iocContainer.Register(r => r.Add<IFoo, Foo>());
_iocContainer.Register(r => r.Add<ITest>().WithFactoryMethod(c => new TestConstructor(c.Resolve<IFoo>(), "someName")));
[Test]
public void TestResolveParameterIsRegisteredWithParameters()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
_iocContainer.Register(r => r.Add<IFoo, FooConstructor>().WithParameters("TestString"));
ITest test = _iocContainer.Resolve<ITest>();
Assert.NotNull(test);
}
ITest test = _iocContainer.Resolve<ITest>("testName");
[Test]
public void TestResolveParameterIsRegisteredWithParameters()
{
_iocContainer.Register(r => r.Add<ITest, TestConstructor>());
_iocContainer.Register(r => r.Add<IFoo, FooConstructor>().WithParameters("TestString"));
Assert.IsInstanceOf<TestConstructor>(test);
}
ITest test = _iocContainer.Resolve<ITest>("testName");
[Test]
public void TestResolveParameterWithParameterThatIsAlreadyExistingSingleton()
{
_iocContainer.Register(r => r.Add<ITest, TestWithFoo>());
_iocContainer.Register(r => r.Add<IFoo, FooConstructor>(Lifestyle.Singleton).WithParameters("TestString"));
Assert.IsInstanceOf<TestConstructor>(test);
}
IFoo foo = _iocContainer.Resolve<IFoo>();
ITest test = _iocContainer.Resolve<ITest>("testName");
[Test]
public void TestResolveParameterWithParameterThatIsAlreadyExistingSingleton()
{
_iocContainer.Register(r => r.Add<ITest, TestWithFoo>());
_iocContainer.Register(r => r.Add<IFoo, FooConstructor>(Lifestyle.Singleton).WithParameters("TestString"));
Assert.IsInstanceOf<TestWithFoo>(test);
Assert.AreSame(foo, ((TestWithFoo) test).TestFoo);
}
IFoo foo = _iocContainer.Resolve<IFoo>();
ITest test = _iocContainer.Resolve<ITest>("testName");
[Test]
public void TestIsTypeRegistered()
{
Assert.False(_iocContainer.IsTypeRegistered<ITest>());
Assert.IsInstanceOf<TestWithFoo>(test);
Assert.AreSame(foo, ((TestWithFoo) test).TestFoo);
}
[Test]
public void TestIsTypeRegistered()
{
Assert.False(_iocContainer.IsTypeRegistered<ITest>());
_iocContainer.Register(r => r.Add<ITest, Test>());
Assert.True(_iocContainer.IsTypeRegistered<ITest>());
_iocContainer.Register(r => r.Add<ITest, Test>());
Assert.True(_iocContainer.IsTypeRegistered<ITest>());
_iocContainer.Register(r => r.Add<Test>());
Assert.True(_iocContainer.IsTypeRegistered<Test>());
}
_iocContainer.Register(r => r.Add<Test>());
Assert.True(_iocContainer.IsTypeRegistered<Test>());
}
}

@ -12,177 +12,176 @@ using LightweightIocContainer.Validation;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class IocValidatorTest
{
[TestFixture]
public class IocValidatorTest
public interface ITest
{
public interface ITest
{
}
}
public interface ITest2
{
public interface ITest2
{
}
}
[UsedImplicitly]
public interface IParameter
{
bool Method();
}
[UsedImplicitly]
public interface IParameter
{
bool Method();
}
private class Test : ITest
{
public Test(IParameter parameter) => parameter.Method();
}
private class Test : ITest
{
public Test(IParameter parameter) => parameter.Method();
}
[UsedImplicitly]
public interface ITestFactory
{
ITest Create(IParameter parameter);
}
[UsedImplicitly]
public interface ITestFactory
{
ITest Create(IParameter parameter);
}
[UsedImplicitly]
public interface ITest2Factory
{
ITest2 InvalidCreate();
ITest2 Create(ITest test);
}
[UsedImplicitly]
public interface ITest2Factory
{
ITest2 InvalidCreate();
ITest2 Create(ITest test);
}
private class Test2 : ITest2
private class Test2 : ITest2
{
public Test2(ITest parameter)
{
public Test2(ITest parameter)
{
}
}
}
[UsedImplicitly]
public interface IInvalidFactory
{
ITest Create();
}
[UsedImplicitly]
public interface IInvalidFactory
{
ITest Create();
}
private class TestInstallerNoFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>();
}
private class TestInstallerNoFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>();
}
private class TestInstallerWithFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<ITestFactory>();
}
private class TestInstallerWithFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<ITestFactory>();
}
private class TestInstallerWithInvalidFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<IInvalidFactory>();
}
private class TestInstallerWithInvalidFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<IInvalidFactory>();
}
private class InvalidTestClassInstaller : IIocInstaller
private class InvalidTestClassInstaller : IIocInstaller
{
public void Install(IRegistrationCollector registration)
{
public void Install(IRegistrationCollector registration)
{
registration.Add<ITest, Test>().WithFactory<ITestFactory>();
registration.Add<ITest2, Test2>().WithFactory<ITest2Factory>();
}
registration.Add<ITest, Test>().WithFactory<ITestFactory>();
registration.Add<ITest2, Test2>().WithFactory<ITest2Factory>();
}
}
[Test]
public void TestValidateWithoutFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerNoFactory());
IocValidator validator = new(iocContainer);
[Test]
public void TestValidateWithoutFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerNoFactory());
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
IocValidator validator = new(iocContainer);
AssertNoMatchingConstructorFoundForType<Test>(aggregateException);
}
[Test]
public void TestValidateWithFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerWithFactory());
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
IocValidator validator = new(iocContainer);
AssertNoMatchingConstructorFoundForType<Test>(aggregateException);
}
validator.Validate();
}
[Test]
public void TestValidateWithFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerWithFactory());
[Test]
public void TestValidateWithParameter()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerNoFactory());
IocValidator validator = new(iocContainer);
IocValidator validator = new(iocContainer);
validator.Validate();
}
Mock<IParameter> parameterMock = new();
parameterMock.Setup(p => p.Method()).Returns(true);
[Test]
public void TestValidateWithParameter()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerNoFactory());
validator.AddParameter<ITest, IParameter>(parameterMock.Object);
IocValidator validator = new(iocContainer);
validator.Validate();
Mock<IParameter> parameterMock = new();
parameterMock.Setup(p => p.Method()).Returns(true);
parameterMock.Verify(p => p.Method(), Times.Never);
}
validator.AddParameter<ITest, IParameter>(parameterMock.Object);
validator.Validate();
[Test]
public void TestValidateWithInvalidParameterWithFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new InvalidTestClassInstaller());
parameterMock.Verify(p => p.Method(), Times.Never);
}
IocValidator validator = new(iocContainer);
Mock<IParameter> parameterMock = new();
validator.AddParameter<ITest, IParameter>(parameterMock.Object);
[Test]
public void TestValidateWithInvalidParameterWithFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new InvalidTestClassInstaller());
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
IocValidator validator = new(iocContainer);
if (aggregateException?.InnerExceptions[0] is not NoMatchingConstructorFoundException noMatchingConstructorFoundException)
{
Assert.Fail();
return;
}
Mock<IParameter> parameterMock = new();
validator.AddParameter<ITest, IParameter>(parameterMock.Object);
if (noMatchingConstructorFoundException.InnerExceptions[0] is not ConstructorNotMatchingException iTest2CtorNotMatchingException)
{
Assert.Fail();
return;
}
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
Assert.IsInstanceOf<DirectResolveWithRegisteredFactoryNotAllowed>(iTest2CtorNotMatchingException.InnerExceptions[0]);
if (aggregateException?.InnerExceptions[0] is not NoMatchingConstructorFoundException noMatchingConstructorFoundException)
{
Assert.Fail();
return;
}
[Test]
public void TestValidateInvalidFactory()
if (noMatchingConstructorFoundException.InnerExceptions[0] is not ConstructorNotMatchingException iTest2CtorNotMatchingException)
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerWithInvalidFactory());
Assert.Fail();
return;
}
IocValidator validator = new(iocContainer);
Assert.IsInstanceOf<DirectResolveWithRegisteredFactoryNotAllowed>(iTest2CtorNotMatchingException.InnerExceptions[0]);
}
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
[Test]
public void TestValidateInvalidFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerWithInvalidFactory());
AssertNoMatchingConstructorFoundForType<Test>(aggregateException);
}
IocValidator validator = new(iocContainer);
private void AssertNoMatchingConstructorFoundForType<T>(AggregateException aggregateException)
{
Exception exception = aggregateException?.InnerExceptions[0];
if (exception is NoMatchingConstructorFoundException noMatchingConstructorFoundException)
Assert.AreEqual(typeof(T), noMatchingConstructorFoundException.Type);
else
Assert.Fail($"Exception is no NoMatchingConstructorFoundException, actual type: {exception?.GetType()}");
}
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
AssertNoMatchingConstructorFoundForType<Test>(aggregateException);
}
private void AssertNoMatchingConstructorFoundForType<T>(AggregateException aggregateException)
{
Exception exception = aggregateException?.InnerExceptions[0];
if (exception is NoMatchingConstructorFoundException noMatchingConstructorFoundException)
Assert.AreEqual(typeof(T), noMatchingConstructorFoundException.Type);
else
Assert.Fail($"Exception is no NoMatchingConstructorFoundException, actual type: {exception?.GetType()}");
}
}

@ -6,96 +6,95 @@ using JetBrains.Annotations;
using LightweightIocContainer;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class MultipleMultitonRegistrationTest
{
[TestFixture]
public class MultipleMultitonRegistrationTest
{
private IocContainer _iocContainer;
private IocContainer _iocContainer;
[UsedImplicitly]
public interface ITest : IProvider
{
[UsedImplicitly]
public interface ITest : IProvider
{
}
}
public interface IProvider
{
int Number { get; }
void DoSomething(int number);
}
public interface IProvider
{
int Number { get; }
void DoSomething(int number);
}
[UsedImplicitly]
public class Test : ITest
{
public int Number { get; private set; }
[UsedImplicitly]
public class Test : ITest
{
public int Number { get; private set; }
public void DoSomething(int number) => Number = number;
}
public void DoSomething(int number) => Number = number;
}
private class MultitonScope
{
private class MultitonScope
{
}
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[Test]
public void TestRegisterAndResolveMultipleMultitonRegistration()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>());
[Test]
public void TestRegisterAndResolveMultipleMultitonRegistration()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>());
MultitonScope scope = new();
MultitonScope scope = new();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
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);
}
IProvider provider = _iocContainer.Resolve<IProvider>(scope);
Assert.NotNull(provider);
Assert.AreEqual(test, provider);
Assert.AreSame(test, provider);
}
[Test]
public void TestRegisterAndResolveMultipleMultitonRegistrationWithDifferentScope()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>());
[Test]
public void TestRegisterAndResolveMultipleMultitonRegistrationWithDifferentScope()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>());
MultitonScope scope = new();
MultitonScope differentScope = new();
MultitonScope scope = new();
MultitonScope differentScope = new();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
IProvider provider = _iocContainer.Resolve<IProvider>(differentScope);
Assert.NotNull(provider);
IProvider provider = _iocContainer.Resolve<IProvider>(differentScope);
Assert.NotNull(provider);
Assert.AreNotEqual(test, provider);
Assert.AreNotSame(test, provider);
}
Assert.AreNotEqual(test, provider);
Assert.AreNotSame(test, provider);
}
[Test]
public void TestMultipleMultitonRegistrationOnCreate()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>().OnCreate(t => t.DoSomething(1)));
[Test]
public void TestMultipleMultitonRegistrationOnCreate()
{
_iocContainer.Register(r => r.AddMultiton<IProvider, ITest, Test, MultitonScope>().OnCreate(t => t.DoSomething(1)));
MultitonScope scope = new();
MultitonScope scope = new();
ITest test = _iocContainer.Resolve<ITest>(scope);
Assert.NotNull(test);
Assert.AreEqual(1, test.Number);
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);
IProvider provider = _iocContainer.Resolve<IProvider>(scope);
Assert.NotNull(provider);
Assert.AreEqual(1, provider.Number);
Assert.AreEqual(test, provider);
Assert.AreSame(test, provider);
}
Assert.AreEqual(test, provider);
Assert.AreSame(test, provider);
}
}

@ -9,31 +9,30 @@ using LightweightIocContainer.Registrations;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class OnCreateTest
{
[TestFixture]
public class OnCreateTest
private interface ITest
{
private interface ITest
{
void DoSomething();
}
void DoSomething();
}
private class Test : ITest
{
public void DoSomething() => throw new Exception();
}
private class Test : ITest
{
public void DoSomething() => throw new Exception();
}
[Test]
public void TestOnCreate()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
ITypedRegistration<ITest, Test> testRegistration = registrationFactory.Register<ITest, Test>(Lifestyle.Transient).OnCreate(t => t.DoSomething());
[Test]
public void TestOnCreate()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
ITypedRegistration<ITest, Test> testRegistration = registrationFactory.Register<ITest, Test>(Lifestyle.Transient).OnCreate(t => t.DoSomething());
Test test = new();
Test test = new();
Assert.Throws<Exception>(() => testRegistration.OnCreateAction!(test));
}
Assert.Throws<Exception>(() => testRegistration.OnCreateAction!(test));
}
}

@ -8,62 +8,61 @@ using LightweightIocContainer;
using LightweightIocContainer.Exceptions;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class OpenGenericRegistrationTest
{
[TestFixture]
public class OpenGenericRegistrationTest
{
private IocContainer _iocContainer;
private IocContainer _iocContainer;
[UsedImplicitly]
[SuppressMessage("ReSharper", "UnusedTypeParameter")]
public interface ITest<T>
{
[UsedImplicitly]
[SuppressMessage("ReSharper", "UnusedTypeParameter")]
public interface ITest<T>
{
}
}
[UsedImplicitly]
public class Test<T> : ITest<T>
{
[UsedImplicitly]
public class Test<T> : ITest<T>
{
}
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[TearDown]
public void TearDown() => _iocContainer.Dispose();
[Test]
public void TestRegisterOpenGenericType()
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>)));
[Test]
public void TestRegisterOpenGenericType()
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>)));
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(test);
}
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(test);
}
[Test]
public void TestRegisterOpenGenericTypeAsSingleton()
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton));
[Test]
public void TestRegisterOpenGenericTypeAsSingleton()
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton));
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(test);
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(test);
ITest<int> secondTest = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(secondTest);
ITest<int> secondTest = _iocContainer.Resolve<ITest<int>>();
Assert.NotNull(secondTest);
Assert.AreEqual(test, secondTest);
Assert.AreSame(test, secondTest);
}
Assert.AreEqual(test, secondTest);
Assert.AreSame(test, secondTest);
}
[Test]
public void TestRegisterOpenGenericTypeAsMultitonThrowsException() =>
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Multiton)));
[Test]
public void TestRegisterOpenGenericTypeAsMultitonThrowsException() =>
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Multiton)));
[Test]
public void TestRegisterNonOpenGenericTypeWithOpenGenericsFunctionThrowsException() =>
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(int), typeof(int))));
}
[Test]
public void TestRegisterNonOpenGenericTypeWithOpenGenericsFunctionThrowsException() =>
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(int), typeof(int))));
}

@ -10,90 +10,89 @@ using LightweightIocContainer.ResolvePlaceholders;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
public class RegistrationBaseTest
{
[TestFixture]
public class RegistrationBaseTest
private interface ITest
{
private interface ITest
{
}
}
private interface IFoo
{
private interface IFoo
{
}
}
private interface IBar
{
private interface IBar
{
}
}
private class Test : ITest
{
private class Test : ITest
{
}
}
[UsedImplicitly]
private class Foo : IFoo
[UsedImplicitly]
private class Foo : IFoo
{
public Foo(IBar bar, ITest test)
{
public Foo(IBar bar, ITest test)
{
}
}
}
private class Bar : IBar
{
private class Bar : IBar
{
}
}
[Test]
public void TestWithParameters()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
[Test]
public void TestWithParameters()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
IBar bar = new Bar();
ITest test = new Test();
IBar bar = new Bar();
ITest test = new Test();
RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(bar, test);
RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(bar, test);
Assert.AreEqual(bar, testRegistration.Parameters![0]);
Assert.AreEqual(test, testRegistration.Parameters[1]);
}
Assert.AreEqual(bar, testRegistration.Parameters![0]);
Assert.AreEqual(test, testRegistration.Parameters[1]);
}
[Test]
public void TestWithParametersDifferentOrder()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
[Test]
public void TestWithParametersDifferentOrder()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
IBar bar = new Bar();
ITest test = new Test();
IBar bar = new Bar();
ITest test = new Test();
RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString"));
RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString"));
Assert.AreEqual(bar, testRegistration.Parameters![0]);
Assert.IsInstanceOf<InternalResolvePlaceholder>(testRegistration.Parameters[1]);
Assert.AreEqual("SomeString", testRegistration.Parameters[2]);
Assert.AreEqual(test, testRegistration.Parameters[3]);
}
Assert.AreEqual(bar, testRegistration.Parameters![0]);
Assert.IsInstanceOf<InternalResolvePlaceholder>(testRegistration.Parameters[1]);
Assert.AreEqual("SomeString", testRegistration.Parameters[2]);
Assert.AreEqual(test, testRegistration.Parameters[3]);
}
[Test]
public void TestWithParametersCalledTwice()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(new Bar()).WithParameters(new Test()));
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((0, new Bar())).WithParameters((1, new Test())));
}
[Test]
public void TestWithParametersCalledTwice()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(new Bar()).WithParameters(new Test()));
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((0, new Bar())).WithParameters((1, new Test())));
}
[Test]
public void TestWithParametersNoParametersGiven()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((object[])null));
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(((int index, object parameter)[])null));
}
[Test]
public void TestWithParametersNoParametersGiven()
{
RegistrationFactory registrationFactory = new(new Mock<IocContainer>().Object);
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters((object[])null));
Assert.Throws<InvalidRegistrationException>(() => registrationFactory.Register<IFoo, Foo>(Lifestyle.Transient).WithParameters(((int index, object parameter)[])null));
}
}

@ -9,63 +9,62 @@ using LightweightIocContainer.Registrations;
using Moq;
using NUnit.Framework;
namespace Test.LightweightIocContainer
namespace Test.LightweightIocContainer;
[TestFixture]
// ReSharper disable MemberHidesStaticFromOuterClass
public class SingleTypeRegistrationTest
{
[TestFixture]
// ReSharper disable MemberHidesStaticFromOuterClass
public class SingleTypeRegistrationTest
private interface IFoo
{
private interface IFoo
{
IBar Bar { get; }
}
IBar Bar { get; }
}
private interface IBar
{
private interface IBar
{
}
}
[UsedImplicitly]
private class Foo : IFoo
{
public Foo(IBar bar) => Bar = bar;
[UsedImplicitly]
private class Foo : IFoo
{
public Foo(IBar bar) => Bar = bar;
public IBar Bar { get; }
}
public IBar Bar { get; }
}
[UsedImplicitly]
private class Bar : IBar
{
[UsedImplicitly]
private class Bar : IBar
{
}
}
[Test]
public void TestSingleTypeRegistrationWithFactoryMethod()
{
IBar bar = new Bar();
[Test]
public void TestSingleTypeRegistrationWithFactoryMethod()
{
IBar bar = new Bar();
Mock<IocContainer> iocContainerMock = new();
iocContainerMock.Setup(c => c.Resolve<IBar>()).Returns(bar);
Mock<IocContainer> iocContainerMock = new();
iocContainerMock.Setup(c => c.Resolve<IBar>()).Returns(bar);
RegistrationFactory registrationFactory = new(iocContainerMock.Object);
ISingleTypeRegistration<IFoo> registration = registrationFactory.Register<IFoo>(Lifestyle.Transient).WithFactoryMethod(c => new Foo(c.Resolve<IBar>()));
RegistrationFactory registrationFactory = new(iocContainerMock.Object);
ISingleTypeRegistration<IFoo> registration = registrationFactory.Register<IFoo>(Lifestyle.Transient).WithFactoryMethod(c => new Foo(c.Resolve<IBar>()));
IFoo foo = registration.FactoryMethod!(iocContainerMock.Object);
Assert.AreEqual(bar, foo.Bar);
}
IFoo foo = registration.FactoryMethod!(iocContainerMock.Object);
Assert.AreEqual(bar, foo.Bar);
}
[Test]
public void TestSingleTypeRegistrationResolveSingleton()
{
IocContainer container = new();
[Test]
public void TestSingleTypeRegistrationResolveSingleton()
{
IocContainer container = new();
IBar bar = new Bar();
container.Register(r => r.Add<IFoo>(Lifestyle.Singleton).WithFactoryMethod(_ => new Foo(bar)));
IBar bar = new Bar();
container.Register(r => r.Add<IFoo>(Lifestyle.Singleton).WithFactoryMethod(_ => new Foo(bar)));
IFoo foo = container.Resolve<IFoo>();
IFoo foo = container.Resolve<IFoo>();
Assert.IsInstanceOf<Foo>(foo);
Assert.AreEqual(bar, foo.Bar);
}
Assert.IsInstanceOf<Foo>(foo);
Assert.AreEqual(bar, foo.Bar);
}
}
Loading…
Cancel
Save