I've been following the very helpful answer here to organise my unit of work and repositories dynamically using SimpleInjector DI.
Using the test service below:
public class TestService
{
public TestService(IRepository<Call> calls){}
}
In the controller:
public class TestingController : Controller
{
private readonly IUnitOfWork _unitOfWork ;
public TestingController(IUnitOfWork unitOfWork, TestService testService)
{
_unitOfWork = unitOfWork;
}
}
And the bootstrapper:
public static class BootStrapper
{
public static void ConfigureWeb(Container container)
{
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
container.Options.ConstructorResolutionBehavior = new GreediestConstructorBehavior();
container.Register<DbContext, OCISContext>(Lifestyle.Scoped);
container.Register<ApplicationUserManager>(Lifestyle.Scoped);
container.Register<ApplicationSignInManager>(Lifestyle.Scoped);
container.Register<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);
container.Register<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork.UnitOfWork>(Lifestyle.Scoped);
container.RegisterCollection(typeof(IRepository<>), typeof(IRepository<>).Assembly);
container.Register<TestService>(Lifestyle.Scoped);
}
I get the error:
An exception of type 'System.InvalidOperationException' occurred in SimpleInjector.dll but was not handled in user code
Additional information: The configuration is invalid. Creating the instance for type TestService failed. The constructor of type TestService contains the parameter with name 'calls' and type
IRepository<Call>
that is not registered. Please ensureIRepository<Call>
is registered, or change the constructor of TestService. There is, however, a registration forIEnumerable<IRepository<Call>>
; Did you mean to depend onIEnumerable<IRepository<Call>>
?
I've also, tried
container.RegisterCollection<IRepository>(new [] {typeof(IRepository)});
container.RegisterCollection(typeof(IRepository), new[] {typeof(IRepository)});
My intention is to get an instance of GenericRepository as this implents IRepository as shown in the answer in the link above.
The exception message you get is actually pretty clear (or at least, to me):
In other words, you made the following registration:
RegisterCollection
means that registrations can be resolved as collection. YourTestService
however depends onIRepository<Call>
instead ofIEnumerable<IRepository<Call>>
.Since I think it is unlikely that your application will use multiple implementations for
IRepository<Call>
at the same time, registration of collections is probably not what you want; there is likely a one-to-one mapping between a closed version of the genericIRepository<T>
interface and an implementation.So instead, make the registration as follows:
This ensures the one-to-one mapping and will throw an exception in case there accidentally are more implementations for the same closed generic type.