Compare commits

..

No commits in common. '3d55222ef0afa76df25e6a84440195adf2d81ce9' and '1b84c307d4f2f1fcb7e2ead4906824b8aa5fb3f0' have entirely different histories.

  1. 5
      LightweightIocContainer.Validation/IocValidator.cs
  2. 2
      LightweightIocContainer.Validation/LightweightIocContainer.Validation.csproj
  3. 2
      LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs
  4. 29
      LightweightIocContainer/IocContainer.cs
  5. 2
      LightweightIocContainer/LightweightIocContainer.csproj
  6. 2
      LightweightIocContainer/Registrations/OpenGenericRegistration.cs
  7. 26
      Test.LightweightIocContainer.Validation/IocValidatorTest.cs
  8. 39
      Test.LightweightIocContainer/OpenGenericRegistrationTest.cs

@ -68,14 +68,9 @@ public class IocValidator(IocContainer iocContainer)
foreach (Type genericArgument in genericArguments.Where(g => g.IsGenericParameter)) foreach (Type genericArgument in genericArguments.Where(g => g.IsGenericParameter))
{ {
Type[] genericParameterConstraints = genericArgument.GetGenericParameterConstraints(); Type[] genericParameterConstraints = genericArgument.GetGenericParameterConstraints();
if (genericParameterConstraints.Any())
{
object mock = Substitute.For(genericParameterConstraints, []); object mock = Substitute.For(genericParameterConstraints, []);
genericParameters.Add(mock.GetType()); genericParameters.Add(mock.GetType());
} }
else
genericParameters.Add(typeof(object));
}
type = type.MakeGenericType(genericParameters.ToArray()); type = type.MakeGenericType(genericParameters.ToArray());
} }

@ -11,7 +11,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DocumentationFile>LightweightIocContainer.Validation.xml</DocumentationFile> <DocumentationFile>LightweightIocContainer.Validation.xml</DocumentationFile>
<VersionPrefix>4.4.0</VersionPrefix> <VersionPrefix>4.4.0</VersionPrefix>
<VersionSuffix>beta7</VersionSuffix> <VersionSuffix>beta5</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

@ -9,5 +9,5 @@ namespace LightweightIocContainer.Interfaces.Registrations;
/// </summary> /// </summary>
public interface IOpenGenericRegistration : ITypedRegistration public interface IOpenGenericRegistration : ITypedRegistration
{ {
internal Type CreateGenericImplementationType<T>();
} }

@ -235,7 +235,10 @@ public class IocContainer : IIocContainer, IIocResolver
switch (result) switch (result)
{ {
case true when registration is IOpenGenericRegistration openGenericRegistration: case true when registration is IOpenGenericRegistration openGenericRegistration:
return (true, new InternalToBeResolvedPlaceholder(openGenericRegistration.CreateGenericImplementationType<T>(), registration, parametersToResolve), null); {
Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments);
return (true, new InternalToBeResolvedPlaceholder(genericImplementationType, registration, parametersToResolve), null);
}
case true: case true:
return (true, new InternalToBeResolvedPlaceholder(registeredType, registration, parametersToResolve), null); return (true, new InternalToBeResolvedPlaceholder(registeredType, registration, parametersToResolve), null);
} }
@ -380,16 +383,21 @@ public class IocContainer : IIocContainer, IIocResolver
/// <returns>A newly created instance of the given <see cref="Type"/></returns> /// <returns>A newly created instance of the given <see cref="Type"/></returns>
private T CreateInstance<T>(IRegistration registration, object?[]? arguments) private T CreateInstance<T>(IRegistration registration, object?[]? arguments)
{ {
T instance = registration switch T instance;
if (registration is IOpenGenericRegistration openGenericRegistration)
{ {
IOpenGenericRegistration openGenericRegistration => Creator.CreateInstance<T>(openGenericRegistration.CreateGenericImplementationType<T>(), arguments), //create generic implementation type from generic arguments of T
ISingleTypeRegistration<T> singleTypeRegistration => singleTypeRegistration.FactoryMethod == null Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments);
? Creator.CreateInstance<T>(singleTypeRegistration.InterfaceType, arguments) instance = Creator.CreateInstance<T>(genericImplementationType, arguments);
: singleTypeRegistration.FactoryMethod(this), }
ILifestyleProvider { Lifestyle: Lifestyle.Multiton } and IMultitonRegistration multitonRegistration => CreateMultitonInstance<T>(multitonRegistration, arguments), else if (registration is ISingleTypeRegistration<T> singleTypeRegistration)
ITypedRegistration defaultRegistration => Creator.CreateInstance<T>(defaultRegistration.ImplementationType, arguments), instance = singleTypeRegistration.FactoryMethod == null ? Creator.CreateInstance<T>(singleTypeRegistration.InterfaceType, arguments) : singleTypeRegistration.FactoryMethod(this);
_ => throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.") else if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Multiton } and IMultitonRegistration multitonRegistration)
}; instance = CreateMultitonInstance<T>(multitonRegistration, arguments);
else if (registration is ITypedRegistration defaultRegistration)
instance = Creator.CreateInstance<T>(defaultRegistration.ImplementationType, arguments);
else
throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.");
if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Singleton }) if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Singleton })
_singletons.TryAdd(GetType<T>(registration), instance); _singletons.TryAdd(GetType<T>(registration), instance);
@ -733,7 +741,6 @@ public class IocContainer : IIocContainer, IIocResolver
private Type GetType<T>(IRegistration registration) => private Type GetType<T>(IRegistration registration) =>
registration switch registration switch
{ {
IOpenGenericRegistration openGenericRegistration => openGenericRegistration.CreateGenericImplementationType<T>(),
ITypedRegistration typedRegistration => typedRegistration.ImplementationType, ITypedRegistration typedRegistration => typedRegistration.ImplementationType,
ISingleTypeRegistration<T> singleTypeRegistration => singleTypeRegistration.InterfaceType, ISingleTypeRegistration<T> singleTypeRegistration => singleTypeRegistration.InterfaceType,
_ => throw new UnknownRegistrationException($"Unknown registration used: {registration.GetType().Name}.") _ => throw new UnknownRegistrationException($"Unknown registration used: {registration.GetType().Name}.")

@ -11,7 +11,7 @@
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<DocumentationFile>LightweightIocContainer.xml</DocumentationFile> <DocumentationFile>LightweightIocContainer.xml</DocumentationFile>
<VersionPrefix>4.4.0</VersionPrefix> <VersionPrefix>4.4.0</VersionPrefix>
<VersionSuffix>beta7</VersionSuffix> <VersionSuffix>beta5</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

@ -29,8 +29,6 @@ internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistrat
/// </summary> /// </summary>
public Type ImplementationType { get; } public Type ImplementationType { get; }
public Type CreateGenericImplementationType<T>() => ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments);
/// <summary> /// <summary>
/// Validate this <see cref="OpenGenericRegistration"/> /// Validate this <see cref="OpenGenericRegistration"/>
/// </summary> /// </summary>

@ -41,12 +41,6 @@ public class IocValidatorTest
[UsedImplicitly] [UsedImplicitly]
public class GenericTest<T> : IGenericTest<T> where T : IConstraint, new(); public class GenericTest<T> : IGenericTest<T> where T : IConstraint, new();
[UsedImplicitly]
public interface IGenericTestWithoutConstraint<T>;
[UsedImplicitly]
public class GenericTestWithoutConstraint<T> : IGenericTestWithoutConstraint<T>;
[UsedImplicitly] [UsedImplicitly]
public interface IGenericTestFactory public interface IGenericTestFactory
{ {
@ -65,15 +59,6 @@ public class IocValidatorTest
} }
} }
[UsedImplicitly]
public class GenericParameterWithoutConstraint : IGenericParameter
{
public GenericParameterWithoutConstraint(IGenericTestWithoutConstraint<IParameter> test)
{
}
}
[UsedImplicitly] [UsedImplicitly]
private class TestViewModelDontIgnoreDesignTimeCtor : ITest private class TestViewModelDontIgnoreDesignTimeCtor : ITest
{ {
@ -337,17 +322,6 @@ public class IocValidatorTest
validator.Validate(); validator.Validate();
} }
[Test]
public void TestValidateOpenGenericTypeWithoutConstraintAsParameter()
{
IocContainer iocContainer = new();
iocContainer.Register(r => r.AddOpenGenerics(typeof(IGenericTestWithoutConstraint<>), typeof(GenericTestWithoutConstraint<>)));
iocContainer.Register(r => r.Add<IGenericParameter, GenericParameterWithoutConstraint>());
IocValidator validator = new(iocContainer);
validator.Validate();
}
private void AssertNoMatchingConstructorFoundForType<T>(AggregateException aggregateException) private void AssertNoMatchingConstructorFoundForType<T>(AggregateException aggregateException)
{ {
Exception exception = aggregateException?.InnerExceptions[0]; Exception exception = aggregateException?.InnerExceptions[0];

@ -21,9 +21,6 @@ public class OpenGenericRegistrationTest
[UsedImplicitly] [UsedImplicitly]
public class Constraint : IConstraint; public class Constraint : IConstraint;
[UsedImplicitly]
public class AnotherConstraint : IConstraint;
[UsedImplicitly] [UsedImplicitly]
[SuppressMessage("ReSharper", "UnusedTypeParameter")] [SuppressMessage("ReSharper", "UnusedTypeParameter")]
public interface ITest<T> where T : IConstraint, new(); public interface ITest<T> where T : IConstraint, new();
@ -53,27 +50,15 @@ public class OpenGenericRegistrationTest
} }
[UsedImplicitly] [UsedImplicitly]
public interface IA public interface IA;
{
ITest<Constraint> Test { get; }
}
[UsedImplicitly] [UsedImplicitly]
public class A(ITest<Constraint> test) : IA public class A : IA
{ {
public ITest<Constraint> Test { get; } = test; public A(ITest<Constraint> test)
}
[UsedImplicitly]
public interface IB
{ {
ITest<AnotherConstraint> Test { get; }
}
[UsedImplicitly] }
public class B(ITest<AnotherConstraint> test) : IB
{
public ITest<AnotherConstraint> Test { get; } = test;
} }
[SetUp] [SetUp]
@ -141,20 +126,4 @@ public class OpenGenericRegistrationTest
IA a = _iocContainer.Resolve<IA>(); IA a = _iocContainer.Resolve<IA>();
Assert.That(a, Is.TypeOf<A>()); Assert.That(a, Is.TypeOf<A>());
} }
[Test]
public void TestOpenGenericTypeAsParameterDifferentGenericParametersResolveDifferentSingletons()
{
_iocContainer.Register(r => r.Add<IA, A>());
_iocContainer.Register(r => r.Add<IB, B>());
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton));
IA a = _iocContainer.Resolve<IA>();
Assert.That(a, Is.TypeOf<A>());
IB b = _iocContainer.Resolve<IB>();
Assert.That(b, Is.TypeOf<B>());
Assert.That(b.Test, Is.Not.SameAs(a.Test));
}
} }
Loading…
Cancel
Save