I'am facing an issue with the architecture set in place while trying to use Autofac.
Error message encountered is the following:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xx.xx.xxxxxxx.HomeController' can be invoked with the available services and parameters: Cannot resolve parameter 'xx.Service.Common.IGenericService
2[xx.Common.Models.EntCountry,System.Int32] countryService' of constructor 'Void .ctor(xx.Service.Common.IGenericService
2[xx.Common.Models.EntCountry,System.Int32])'.
Repository Interface and Class
public interface IGenericRepository<T,TId>
where T: class , IEntity<TId>
{...}
public abstract class GenericRepository<T, TId> : IGenericRepository<T, TId>
where T : class, IEntity<TId>
where TId : class {}
Service Interface and Class
public interface IGenericService<T,TId> where T : class , IEntity<TId>
{...}
public abstract class GenericService<T, TId> : IGenericService<T, TId>
where T : class, IEntity<TId>
where TId : class{...}
Controller Code
public class HomeController : Controller
{
private readonly IGenericService<EntCountry, int> _countryService;
public HomeController(IGenericService<EntCountry, int> countryService)
{
_countryService = countryService;
}
// GET: Home
public ActionResult Index()
{
var countries = _countryService.GetAll();
return View();
}
}
My Autofac configuration for services and repository is the following:
builder.RegisterAssemblyTypes(Assembly.Load("XX.Data"))
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.AsSelf()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
.InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(Assembly.Load("XX.Service"))
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.AsSelf()
.PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies)
.InstancePerLifetimeScope();
I tried to use the Register Generic method, but I still got the same error
builder.RegisterGeneric(typeof(GenericRepository<,>))
.As(typeof(IGenericRepository<,>))
.AsSelf()
.InstancePerDependency();
Thanks for your help.
best regards.
The error message indicates that IGenericService<EntCountry, Int32>
is not registered.
Because GenericService
is abstract the first solution would be to have an implementation of such a class
public class FooService : GenericService<Foo, Int32>
{ }
Then Autofac will register FooService
as IGenericService<Foo, Int32>
If you don't want to have an implementation but only use GenericService<T, TId>
you will have to remove the abstract
modifier and change how you register your type in Autofac.
Unfortunately there is no easy way to register an open generic type when scanning assemblies. There is an active open issue about this in Autofac Github : Support registering open generic types when scanning assemblies
The easiest solution is to register this type manually
builder.RegisterGeneric(typeof(GenericService<,>))
.AsImplementedInterfaces();
If it is not possible have a look at the Github issue there is some solution you could play with.
There will also be another issue with the code provided. The IGenericService<T, TId>
has a class constraint (where TId : class
) but in the exception TId
is a Int32
wich is not valid for the .net runtime. You should remove the class constraint or change the type of TId
.