Heres my setup code:
Dim builder As New ContainerBuilder
Dim assemblies = BuildManager.GetReferencedAssemblies().Cast(Of Assembly).ToArray
builder.RegisterModule(Of AutofacWebTypesModule)
builder.RegisterAssemblyTypes(assemblies).AsClosedTypesOf(GetType(IGenericRepository(Of)))
'Controllers
builder.RegisterControllers(assemblies)
'Model Binders
builder.RegisterModelBinders(assemblies)
builder.RegisterModelBinderProvider()
Dim container = builder.Build
And controller code:
Public Class TestController
Inherits System.Web.Mvc.Controller
Public Sub New(manager As IGenericRepository(Of TestObject))
End Sub
Public Function Test() As ContentResult
Return Content("OK")
End Function
End Class
Now when i navigate to /Test/Test
I get the following error:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProject.TestController' can be invoked with the available services and parameters: Cannot resolve parameter 'MyProject.IGenericRepository
1[MyProject.TestObject] manager' of constructor 'Void .ctor(MyProject.IGenericRepository
1[MyProject.TestObject])'.
What is the proper way to register this open generic with autofac?
I cant use something like builder.RegisterGeneric(GetType(GenericRepository(Of))).As(GetType(IGenericRepository(Of)))
because the concrete class is in a different, unreferenced project
The AsClosedTypesOf
method will register closed type (not generic) that implement the specific open type.
Your code will work if one assembly contains a closed implementation of IGenericRepository<TestObject>
public class TestRespository : IGenericRepository<TestObject>
{ }
In your case you want to register an open generic, without assembly scanning it is done by using
builder.RegisterGeneric(typeof(GenericRepository<>)).As(typeof(IGenericRepository<>))
but due to limitation explained in this Github issue (Support registering open generic types when scanning assemblies) it is not possible.
One common workaround is to do your own assembly scanning :
var repositories = assembly.GetTypes().Where(t =>
{
return t.GetTypeInfo()
.ImplementedInterfaces.Any(
i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IGenericRepository<>));
});
foreach (var repository in repositories)
{
builder.RegisterGeneric(repository).As(typeof(IGenericRepository<>));
}