Skip to content

Commit

Permalink
Fix #1315: Use base type for open generic arg matching.
Browse files Browse the repository at this point in the history
  • Loading branch information
tillig committed Mar 18, 2022
1 parent 82dedce commit 219ba41
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 1 deletion.
29 changes: 28 additions & 1 deletion src/Autofac/Features/OpenGenerics/OpenGenericServiceBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,18 @@ public static bool TryBindOpenGenericDelegateService(

if (!serviceType.IsInterface)
{
return TryFindServiceArgumentsForImplementation(implementationType, serviceGenericArguments, serviceTypeDefinition.GetGenericArguments());
var baseType = GetGenericBaseType(implementationType, serviceTypeDefinition);
if (baseType == null)
{
// If it's not an interface, the implementation type MUST have derived from
// the generic service type at some point or there's no way to cast.
return Array.Empty<Type>();
}

return TryFindServiceArgumentsForImplementation(
implementationType,
serviceGenericArguments,
baseType.GenericTypeArguments);
}

var availableArguments = GetInterfaces(implementationType, serviceType)
Expand All @@ -199,6 +210,22 @@ public static bool TryBindOpenGenericDelegateService(
.ToArray();
}

private static Type? GetGenericBaseType(Type implementationType, Type serviceTypeDefinition)
{
var baseType = implementationType.BaseType;
while (baseType != null)
{
if (baseType.IsGenericType && baseType.GetGenericTypeDefinition() == serviceTypeDefinition)
{
break;
}

baseType = baseType.BaseType;
}

return baseType;
}

private static Type[] GetInterfaces(Type implementationType, Type serviceType) =>
implementationType.GetInterfaces()
.Where(i => i.Name == serviceType.Name && i.Namespace == serviceType.Namespace)
Expand Down
23 changes: 23 additions & 0 deletions test/Autofac.Specification.Test/Registration/OpenGenericTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,30 @@ public void ResolveWithMultipleCandidatesLimitedByGenericConstraintsShouldSuccee
Assert.NotNull(resolved);
}

// Issue #1315: Class services fail to resolve if the names on the type
// arguments are changed.
[Fact]
public void ResolveClassWithRenamedTypeArguments()
{
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterGeneric(typeof(DerivedRepository<,>)).As(typeof(BaseRepository<,>));

var container = containerBuilder.Build();
var resolved = container.Resolve<BaseRepository<string, int>>();
Assert.IsType<DerivedRepository<int, string>>(resolved);
}

private class SelfComponent<T> : IImplementedInterface<T>
{
}

private class BaseRepository<T1, T2>
{
}

// Issue #1315: Class services fail to resolve if the names on the type
// arguments are changed.
private class DerivedRepository<TSecond, TFirst> : BaseRepository<TFirst, TSecond>
{
}
}

0 comments on commit 219ba41

Please sign in to comment.