简体   繁体   中英

Register generic types in SimpleInjector Version 3

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 ensure IRepository<Call> is registered, or change the constructor of TestService. There is, however, a registration for IEnumerable<IRepository<Call>> ; Did you mean to depend on IEnumerable<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):

Please ensure IRepository<Call> is registered, or change the constructor of TestService. There is, however, a registration for IEnumerable<IRepository<Call>> ; Did you mean to depend on IEnumerable<IRepository<Call>> ?

In other words, you made the following registration:

container.RegisterCollection(typeof(IRepository<>), typeof(IRepository<>).Assembly);

RegisterCollection means that registrations can be resolved as collection. Your TestService however depends on IRepository<Call> instead of IEnumerable<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 generic IRepository<T> interface and an implementation.

So instead, make the registration as follows:

container.Register(typeof(IRepository<>), new[] { typeof(IRepository<>).Assembly });

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM