- add ignoreConstructor Attribute

ImplementExpressionTrees
Simon G 3 years ago
parent ca9a183b68
commit 8b9edbfbe2
  1. 16
      LightweightIocContainer/Annotations/IocIgnoreConstructorAttribute.cs
  2. 7
      LightweightIocContainer/IocContainer.cs
  3. 5
      LightweightIocContainer/LightweightIocContainer.xml
  4. 104
      Test.LightweightIocContainer.Validation/IocValidatorTest.cs

@ -0,0 +1,16 @@
// Author: Gockner, Simon
// Created: 2022-09-01
// Copyright(c) 2022 SimonG. All Rights Reserved.
using LightweightIocContainer.Interfaces;
namespace LightweightIocContainer.Annotations;
/// <summary>
/// If a constructor is annotated with this attribute it will be ignored by the <see cref="IIocContainer"/>
/// </summary>
[AttributeUsage(AttributeTargets.Constructor)]
public class IocIgnoreConstructorAttribute : Attribute
{
}

@ -4,6 +4,7 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using LightweightIocContainer.Annotations;
using LightweightIocContainer.Exceptions; using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Factories; using LightweightIocContainer.Interfaces.Factories;
@ -572,7 +573,11 @@ public class IocContainer : IIocContainer, IIocResolver
/// <exception cref="NoPublicConstructorFoundException">No public constructor was found for the given <see cref="Type"/></exception> /// <exception cref="NoPublicConstructorFoundException">No public constructor was found for the given <see cref="Type"/></exception>
private List<ConstructorInfo> TryGetSortedConstructors(Type type) private List<ConstructorInfo> TryGetSortedConstructors(Type type)
{ {
List<ConstructorInfo> sortedConstructors = type.GetConstructors().OrderByDescending(c => c.GetParameters().Length).ToList(); List<ConstructorInfo> sortedConstructors = type.GetConstructors()
.Where(c => c.GetCustomAttribute<IocIgnoreConstructorAttribute>() == null)
.OrderByDescending(c => c.GetParameters().Length)
.ToList();
if (!sortedConstructors.Any()) //no public constructor available if (!sortedConstructors.Any()) //no public constructor available
throw new NoPublicConstructorFoundException(type); throw new NoPublicConstructorFoundException(type);

@ -13,6 +13,11 @@
<param name="action">The given <see cref="T:System.Action`1"/> to convert</param> <param name="action">The given <see cref="T:System.Action`1"/> to convert</param>
<returns>An <see cref="T:System.Action`1"/> converted from the given <see cref="T:System.Action`1"/></returns> <returns>An <see cref="T:System.Action`1"/> converted from the given <see cref="T:System.Action`1"/></returns>
</member> </member>
<member name="T:LightweightIocContainer.Annotations.IocIgnoreConstructorAttribute">
<summary>
If a constructor is annotated with this attribute it will be ignored by the <see cref="T:LightweightIocContainer.Interfaces.IIocContainer"/>
</summary>
</member>
<member name="T:LightweightIocContainer.Creator"> <member name="T:LightweightIocContainer.Creator">
<summary> <summary>
Helper for dynamic instance creation Helper for dynamic instance creation

@ -4,6 +4,7 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using LightweightIocContainer; using LightweightIocContainer;
using LightweightIocContainer.Annotations;
using LightweightIocContainer.Exceptions; using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations; using LightweightIocContainer.Interfaces.Registrations;
@ -21,11 +22,6 @@ public class IocValidatorTest
} }
public interface ITest2
{
}
[UsedImplicitly] [UsedImplicitly]
public interface IParameter public interface IParameter
{ {
@ -36,32 +32,36 @@ public class IocValidatorTest
{ {
public Test(IParameter parameter) => parameter.Method(); public Test(IParameter parameter) => parameter.Method();
} }
private class Test2 : ITest2 private class TestViewModel : ITest
{ {
public Test2(ITest dependency) public TestViewModel(IParameter parameter) => parameter.Method();
{
}
}
[IocIgnoreConstructor]
public TestViewModel() => throw new Exception();
}
private class Parameter : IParameter
{
public bool Method() => throw new NotImplementedException();
}
[UsedImplicitly] [UsedImplicitly]
public interface ITestFactory public interface ITestFactory
{ {
ITest Create(IParameter parameter); ITest Create(IParameter parameter);
} }
[UsedImplicitly] [UsedImplicitly]
public interface ITest2Factory public interface IInvalidTestFactory
{ {
ITest2 InvalidCreate(); ITest Create();
ITest2 Create(ITest test);
} }
[UsedImplicitly] [UsedImplicitly]
public interface IInvalidFactory public interface IParameterFactory
{ {
ITest Create(); IParameter Create();
} }
private class TestInstallerNoFactory : IIocInstaller private class TestInstallerNoFactory : IIocInstaller
@ -76,18 +76,36 @@ public class IocValidatorTest
private class TestInstallerWithInvalidFactory : IIocInstaller private class TestInstallerWithInvalidFactory : IIocInstaller
{ {
public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<IInvalidFactory>(); public void Install(IRegistrationCollector registration) => registration.Add<ITest, Test>().WithFactory<IInvalidTestFactory>();
} }
private class InvalidTestClassInstaller : IIocInstaller private class TestInstallerInvalidFactoryParameterRegisteredWithoutFactory : IIocInstaller
{ {
public void Install(IRegistrationCollector registration) public void Install(IRegistrationCollector registration)
{ {
registration.Add<ITest, Test>().WithFactory<ITestFactory>(); registration.Add<ITest, Test>().WithFactory<IInvalidTestFactory>();
registration.Add<ITest2, Test2>().WithFactory<ITest2Factory>(); registration.Add<IParameter, Parameter>();
} }
} }
private class TestInstallerInvalidFactoryParameterRegisteredWithFactory : IIocInstaller
{
public void Install(IRegistrationCollector registration)
{
registration.Add<ITest, Test>().WithFactory<IInvalidTestFactory>();
registration.Add<IParameter, Parameter>().WithFactory<IParameterFactory>();
}
}
private class TestInstallerInvalidFactoryViewModel : IIocInstaller
{
public void Install(IRegistrationCollector registration)
{
registration.Add<ITest, TestViewModel>().WithFactory<IInvalidTestFactory>();
registration.Add<IParameter, Parameter>().WithFactory<IParameterFactory>();
}
}
[Test] [Test]
public void TestValidateWithoutFactory() public void TestValidateWithoutFactory()
{ {
@ -129,12 +147,23 @@ public class IocValidatorTest
parameterMock.Verify(p => p.Method(), Times.Never); parameterMock.Verify(p => p.Method(), Times.Never);
} }
[Test]
public void TestValidateWithInvalidFactoryParameterWithoutFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerInvalidFactoryParameterRegisteredWithoutFactory());
IocValidator validator = new(iocContainer);
validator.Validate();
}
[Test] [Test]
public void TestValidateWithInvalidParameterWithFactory() public void TestValidateWithInvalidParameterWithFactory()
{ {
IocContainer iocContainer = new(); IocContainer iocContainer = new();
iocContainer.Install(new InvalidTestClassInstaller()); iocContainer.Install(new TestInstallerInvalidFactoryParameterRegisteredWithFactory());
IocValidator validator = new(iocContainer); IocValidator validator = new(iocContainer);
@ -157,6 +186,31 @@ public class IocValidatorTest
Assert.IsInstanceOf<DirectResolveWithRegisteredFactoryNotAllowed>(iTest2CtorNotMatchingException.InnerExceptions[0]); Assert.IsInstanceOf<DirectResolveWithRegisteredFactoryNotAllowed>(iTest2CtorNotMatchingException.InnerExceptions[0]);
} }
[Test]
public void TestValidateViewModelWithInvalidParameterWithFactory()
{
IocContainer iocContainer = new();
iocContainer.Install(new TestInstallerInvalidFactoryViewModel());
IocValidator validator = new(iocContainer);
AggregateException aggregateException = Assert.Throws<AggregateException>(() => validator.Validate());
if (aggregateException?.InnerExceptions[0] is not NoMatchingConstructorFoundException noMatchingConstructorFoundException)
{
Assert.Fail($"First element of {nameof(aggregateException.InnerExceptions)} is not of type {nameof(NoMatchingConstructorFoundException)}.");
return;
}
if (noMatchingConstructorFoundException.InnerExceptions[0] is not ConstructorNotMatchingException iTest2CtorNotMatchingException)
{
Assert.Fail($"First element of {nameof(noMatchingConstructorFoundException.InnerExceptions)} is not of type {nameof(ConstructorNotMatchingException)}.");
return;
}
Assert.IsInstanceOf<DirectResolveWithRegisteredFactoryNotAllowed>(iTest2CtorNotMatchingException.InnerExceptions[0]);
}
[Test] [Test]
public void TestValidateInvalidFactory() public void TestValidateInvalidFactory()

Loading…
Cancel
Save