- fix factories of open generic registration

ImplementExpressionTrees
Simon G. 2 years ago
parent 8048706df4
commit 7cc36927ed
Signed by: SimonG
GPG Key ID: 7CD6DBFB1B2786ED
  1. 20
      LightweightIocContainer/Factories/TypedFactory.cs
  2. 9
      LightweightIocContainer/Registrations/OpenGenericRegistration.cs
  3. 36
      Test.LightweightIocContainer/OpenGenericRegistrationTest.cs

@ -75,6 +75,26 @@ public class TypedFactory<TFactory> : TypedFactoryBase<TFactory>, ITypedFactory<
MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual,
createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray());
if (createMethod.IsGenericMethod)
{
Type[] genericArguments = createMethod.GetGenericMethodDefinition().GetGenericArguments();
string[] genericArgumentNames = genericArguments.Select(a => a.Name).ToArray();
GenericTypeParameterBuilder[] genericParameters = methodBuilder.DefineGenericParameters(genericArgumentNames);
foreach (GenericTypeParameterBuilder genericParameter in genericParameters)
{
Type genericType = genericArguments.First(a => a.Name == genericParameter.Name);
genericParameter.SetGenericParameterAttributes(genericType.GenericParameterAttributes);
genericParameter.SetInterfaceConstraints(genericType.GetGenericParameterConstraints().Where(c => c.IsInterface).ToArray());
Type? typeConstraint = genericType.GetGenericParameterConstraints().FirstOrDefault(c => !c.IsInterface);
if (typeConstraint is not null)
genericParameter.SetBaseTypeConstraint(typeConstraint);
}
}
typeBuilder.DefineMethodOverride(methodBuilder, createMethod);
ILGenerator generator = methodBuilder.GetILGenerator();

@ -43,6 +43,15 @@ internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistrat
base.Validate();
}
protected override void ValidateFactory()
{
if (Factory == null)
return;
if (Factory.CreateMethods.All(c => c.ReturnType.Name != InterfaceType.Name))
throw new InvalidFactoryRegistrationException($"No create method that can create {InterfaceType}.");
}
public override bool Equals(object? obj) => obj is OpenGenericRegistration openGenericRegistration &&
base.Equals(obj) &&
ImplementationType == openGenericRegistration.ImplementationType;

@ -15,19 +15,36 @@ public class OpenGenericRegistrationTest
{
private IocContainer _iocContainer;
[UsedImplicitly]
public interface IConstraint
{
}
[UsedImplicitly]
public class Constraint : IConstraint
{
}
[UsedImplicitly]
[SuppressMessage("ReSharper", "UnusedTypeParameter")]
public interface ITest<T>
public interface ITest<T> where T : IConstraint, new()
{
}
[UsedImplicitly]
public class Test<T> : ITest<T>
public class Test<T> : ITest<T> where T : IConstraint, new()
{
}
public interface ITestFactory
{
ITest<T> Create<T>() where T : IConstraint, new();
}
[SetUp]
public void SetUp() => _iocContainer = new IocContainer();
@ -39,7 +56,7 @@ public class OpenGenericRegistrationTest
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>)));
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
ITest<Constraint> test = _iocContainer.Resolve<ITest<Constraint>>();
Assert.NotNull(test);
}
@ -48,10 +65,10 @@ public class OpenGenericRegistrationTest
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton));
ITest<int> test = _iocContainer.Resolve<ITest<int>>();
ITest<Constraint> test = _iocContainer.Resolve<ITest<Constraint>>();
Assert.NotNull(test);
ITest<int> secondTest = _iocContainer.Resolve<ITest<int>>();
ITest<Constraint> secondTest = _iocContainer.Resolve<ITest<Constraint>>();
Assert.NotNull(secondTest);
Assert.AreEqual(test, secondTest);
@ -65,4 +82,13 @@ public class OpenGenericRegistrationTest
[Test]
public void TestRegisterNonOpenGenericTypeWithOpenGenericsFunctionThrowsException() =>
Assert.Throws<InvalidRegistrationException>(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(int), typeof(int))));
[Test]
public void TestRegisterFactoryOfOpenGenericType()
{
_iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>)).WithFactory<ITestFactory>());
ITestFactory testFactory = _iocContainer.Resolve<ITestFactory>();
ITest<Constraint> test = testFactory.Create<Constraint>();
Assert.IsInstanceOf<ITest<Constraint>>(test);
}
}
Loading…
Cancel
Save