Skip to content

Commit 59c7205

Browse files
committed
Bug fix: Open-generic registrations for types with generic array generic type arguments couldn't be resolved Fixes #996
1 parent fd9e9b8 commit 59c7205

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/SimpleInjector.Tests.Unit/RegisterOpenGenericTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,75 @@ public void Register_OverridingNonConditionalOpenGenericTypeWithNewTypeConstrain
13481348
actualInstance: container.GetInstance<INewConstraintedGeneric<int>>());
13491349
}
13501350

1351+
[TestMethod]
1352+
public void Verify_ClosedGenericRegistrationOfOpenGenericTypeWithGenericArrayType_Succeeds()
1353+
{
1354+
var container = new Container();
1355+
1356+
container.Register<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>, GenericArrayQueryHandler<int>>();
1357+
1358+
container.Register<ServiceDependingOn<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>>>();
1359+
1360+
container.Verify();
1361+
}
1362+
1363+
[TestMethod]
1364+
public void Verify_ClosedGenericRegistrationOfOpenGenericTypeWithGenericArrayTypeAfterOtherClosedRegistrationForSameType_Succeeds()
1365+
{
1366+
var container = new Container();
1367+
1368+
container.Register<IQueryHandler<SimpleQuery, object>, SimpleQueryHandler>();
1369+
1370+
container.Register<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>, GenericArrayQueryHandler<int>>();
1371+
1372+
container.Register<ServiceDependingOn<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>>>();
1373+
1374+
container.Verify();
1375+
}
1376+
1377+
[TestMethod]
1378+
public void Verify_OpenGenericRegistrationOfOpenGenericTypeWithGenericArrayTypeAfterClosedRegistrationForSameType_Succeeds()
1379+
{
1380+
var container = new Container();
1381+
1382+
container.Register<IQueryHandler<SimpleQuery, object>, SimpleQueryHandler>();
1383+
1384+
container.Register(typeof(IQueryHandler<,>), typeof(GenericArrayQueryHandler<>));
1385+
1386+
container.Register<ServiceDependingOn<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>>>();
1387+
1388+
container.Verify();
1389+
}
1390+
1391+
[TestMethod]
1392+
public void GetInstance_OpenGenericRegistrationOfOpenGenericTypeWithGenericArrayType_Succeeds()
1393+
{
1394+
var container = new Container();
1395+
1396+
container.Register(typeof(IQueryHandler<,>), typeof(GenericArrayQueryHandler<>));
1397+
1398+
container.GetInstance<IQueryHandler<GenericArrayQuery<int>, Tuple<int>[]>>();
1399+
}
1400+
1401+
[TestMethod]
1402+
public void GetInstance_OpenGenericRegistrationOfOpenGenericTypeWithGenericEnumerableElementType_Succeeds()
1403+
{
1404+
var container = new Container();
1405+
1406+
container.Register(typeof(IQueryHandler<,>), typeof(GenericEnumerableQueryHandler<>));
1407+
1408+
container.GetInstance<IQueryHandler<GenericEnumerableQuery<int>, IEnumerable<Tuple<int>>>>();
1409+
}
1410+
1411+
public class SimpleQuery : IQuery<object> { }
1412+
public class SimpleQueryHandler : IQueryHandler<SimpleQuery, object> { }
1413+
1414+
public class GenericArrayQuery<T> : IQuery<Tuple<T>[]> { }
1415+
public class GenericArrayQueryHandler<T> : IQueryHandler<GenericArrayQuery<T>, Tuple<T>[]> { }
1416+
1417+
public class GenericEnumerableQuery<T> : IQuery<IEnumerable<Tuple<T>>> { }
1418+
public class GenericEnumerableQueryHandler<T> : IQueryHandler<GenericEnumerableQuery<T>, IEnumerable<Tuple<T>>> { }
1419+
13511420
public interface IService<T> { }
13521421

13531422
public class ServiceImplementation<T> : IService<T> { }

src/SimpleInjector/Internals/GenericArgumentFinder.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ private ArgumentMapping[] ConvertToOpenImplementationArgumentMappingsRecursive(
173173
return new ArgumentMapping[] { mapping };
174174
}
175175

176-
var argumentTypeDefinition = mapping.Argument.GetGenericTypeDefinition();
176+
var argumentTypeDefinition = mapping.Argument.IsArray
177+
? this.GetGenericArrayDefinition(mapping.Argument)
178+
: mapping.Argument.GetGenericTypeDefinition();
177179

178180
// Try to get mappings for each type in the type hierarchy that is compatible to the argument.
179181
return (
@@ -183,6 +185,23 @@ from arg in this.ConvertToOpenImplementationArgumentMappingsForType(mapping, typ
183185
.ToArray();
184186
}
185187

188+
private Type GetGenericArrayDefinition(Type type)
189+
{
190+
var elementType = type.GetElementType();
191+
192+
if (elementType.IsArray)
193+
{
194+
elementType = this.GetGenericArrayDefinition(elementType);
195+
}
196+
else if (elementType.IsGenericType())
197+
{
198+
elementType = elementType.GetGenericTypeDefinition();
199+
}
200+
201+
return elementType.MakeArrayType();
202+
}
203+
204+
186205
private ArgumentMapping[] ConvertToOpenImplementationArgumentMappingsForType(
187206
ArgumentMapping mapping, Type type, IList<Type> processedTypes)
188207
{

0 commit comments

Comments
 (0)