- allow registration of same types if registered equally

pull/57/head
Simon G 4 years ago
parent f4ec79331a
commit 3bea00c409
  1. 6
      LightweightIocContainer/Exceptions/MultipleRegistrationException.cs
  2. 4
      LightweightIocContainer/IocContainer.cs
  3. 4
      LightweightIocContainer/LightweightIocContainer.xml
  4. 2
      LightweightIocContainer/Registrations/MultipleRegistration.cs
  5. 6
      LightweightIocContainer/Registrations/MultitonRegistration.cs
  6. 6
      LightweightIocContainer/Registrations/OpenGenericRegistration.cs
  7. 30
      LightweightIocContainer/Registrations/RegistrationBase.cs
  8. 16
      LightweightIocContainer/Registrations/SingleTypeRegistration.cs
  9. 8
      LightweightIocContainer/Registrations/TypedFactoryRegistration.cs
  10. 19
      LightweightIocContainer/Registrations/TypedRegistration.cs
  11. 16
      Test.LightweightIocContainer/IocContainerTest.cs

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

@ -88,8 +88,8 @@ namespace LightweightIocContainer
/// <exception cref="MultipleRegistrationException">The <see cref="Type"/> is already registered in this <see cref="IocContainer"/></exception> /// <exception cref="MultipleRegistrationException">The <see cref="Type"/> is already registered in this <see cref="IocContainer"/></exception>
private void Register(IRegistration registration) private void Register(IRegistration registration)
{ {
//if type is already registered //fixMe: Remove and check if already registered registration is the same IRegistration? sameTypeRegistration = Registrations.FirstOrDefault(r => r.InterfaceType == registration.InterfaceType);
if (Registrations.Any(r => r.InterfaceType == registration.InterfaceType)) if (sameTypeRegistration != null && !registration.Equals(sameTypeRegistration)) //if type is already registered differently
throw new MultipleRegistrationException(registration.InterfaceType); throw new MultipleRegistrationException(registration.InterfaceType);
if (registration is IInternalValidationProvider validationProvider) if (registration is IInternalValidationProvider validationProvider)

@ -234,12 +234,12 @@
</member> </member>
<member name="T:LightweightIocContainer.Exceptions.MultipleRegistrationException"> <member name="T:LightweightIocContainer.Exceptions.MultipleRegistrationException">
<summary> <summary>
The <see cref="T:System.Type"/> is already registered in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/> The <see cref="T:System.Type"/> is already registered differently in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/>
</summary> </summary>
</member> </member>
<member name="M:LightweightIocContainer.Exceptions.MultipleRegistrationException.#ctor(System.Type)"> <member name="M:LightweightIocContainer.Exceptions.MultipleRegistrationException.#ctor(System.Type)">
<summary> <summary>
The <see cref="T:System.Type"/> is already registered in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/> The <see cref="T:System.Type"/> is already registered differently in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/>
</summary> </summary>
<param name="type">The <see cref="T:System.Type"/> that is already registered in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></param> <param name="type">The <see cref="T:System.Type"/> that is already registered in this <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/></param>
</member> </member>

@ -30,7 +30,7 @@ namespace LightweightIocContainer.Registrations
/// <summary> /// <summary>
/// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="MultipleRegistration{TInterface1,TInterface2}"/> /// A <see cref="List{T}"/> of <see cref="IRegistration"/>s that are registered within this <see cref="MultipleRegistration{TInterface1,TInterface2}"/>
/// </summary> /// </summary>
public List<IRegistration> Registrations { get; protected set; } public List<IRegistration> Registrations { get; protected init; }
} }
/// <summary> /// <summary>

@ -49,5 +49,11 @@ namespace LightweightIocContainer.Registrations
base.ValidateFactory(); 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);
} }
} }

@ -43,5 +43,11 @@ namespace LightweightIocContainer.Registrations
base.Validate(); 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);
} }
} }

@ -213,5 +213,35 @@ namespace LightweightIocContainer.Registrations
} }
} }
} }
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 (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;
return InterfaceType == registrationBase.InterfaceType &&
Lifestyle == registrationBase.Lifestyle &&
DisposeStrategy == registrationBase.DisposeStrategy;
}
public override int GetHashCode() => HashCode.Combine(InterfaceType, (int) Lifestyle);
} }
} }

@ -41,5 +41,21 @@ namespace LightweightIocContainer.Registrations
FactoryMethod = factoryMethod; FactoryMethod = factoryMethod;
return this; 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();
} }
} }

@ -12,7 +12,7 @@ namespace LightweightIocContainer.Registrations
/// The registration that is used to register an abstract typed factory /// The registration that is used to register an abstract typed factory
/// </summary> /// </summary>
/// <typeparam name="TFactory">The <see cref="Type"/> of the abstract typed factory</typeparam> /// <typeparam name="TFactory">The <see cref="Type"/> of the abstract typed factory</typeparam>
public class TypedFactoryRegistration<TFactory> : ITypedFactoryRegistration<TFactory> internal class TypedFactoryRegistration<TFactory> : ITypedFactoryRegistration<TFactory>
{ {
/// <summary> /// <summary>
/// The registration that is used to register an abstract typed factory /// The registration that is used to register an abstract typed factory
@ -29,5 +29,11 @@ namespace LightweightIocContainer.Registrations
/// The class that contains the implemented abstract factory of this <see cref="TypedFactoryRegistration{TFactory}"/> /// The class that contains the implemented abstract factory of this <see cref="TypedFactoryRegistration{TFactory}"/>
/// </summary> /// </summary>
public ITypedFactory<TFactory> Factory { get; } 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 int GetHashCode() => HashCode.Combine(InterfaceType);
} }
} }

@ -58,5 +58,24 @@ namespace LightweightIocContainer.Registrations
/// Validate the <see cref="DisposeStrategy"/> for the <see cref="ImplementationType"/> and <see cref="Lifestyle"/> /// Validate the <see cref="DisposeStrategy"/> for the <see cref="ImplementationType"/> and <see cref="Lifestyle"/>
/// </summary> /// </summary>
protected override void ValidateDisposeStrategy() => ValidateDisposeStrategy(ImplementationType); protected override void ValidateDisposeStrategy() => ValidateDisposeStrategy(ImplementationType);
public override bool Equals(object? obj)
{
if (obj is not TypedRegistration<TInterface, TImplementation> typedRegistration)
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;
}
public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), ImplementationType);
} }
} }

@ -146,13 +146,27 @@ namespace Test.LightweightIocContainer
public void TestInvalidMultitonRegistration() => Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Multiton))); public void TestInvalidMultitonRegistration() => Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, Test>(Lifestyle.Multiton)));
[Test] [Test]
public void TestRegisterMultiple() public void TestRegisterMultipleDifferent()
{ {
_iocContainer.Register(r => r.Add<ITest, Test>()); _iocContainer.Register(r => r.Add<ITest, Test>());
MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, TestConstructor>())); MultipleRegistrationException exception = Assert.Throws<MultipleRegistrationException>(() => _iocContainer.Register(r => r.Add<ITest, TestConstructor>()));
Assert.AreEqual(typeof(ITest), exception?.Type); 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 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] [Test]
public void TestResolveNotRegistered() public void TestResolveNotRegistered()
{ {

Loading…
Cancel
Save