0

I've started down an Autofac rabbit hole that I think I need to pull myself out of. I have a .NET MVC site where a user can list their favorite players per sport (baseball, basketball, etc.) I have a Players controller, and I'm injecting IPlayerService. However, my problem is that the service needs to know which sport we're dealing with. I'm currently using keyed parameters with a Sports enum which I'm registering in Autofac like so:

foreach (var value in Enum.GetValues(typeof(Sports)))
{
    var sport = (Sports)value;

    builder.RegisterType<PlayerService>()
        .Keyed<IPlayerService>(sport)
        .WithParameter(new NamedParameter("sport", sport))
        .InstancePerLifetimeScope();
}

The sport also needs to get pushed down to IPlayerRepository, which I have registered almost exactly the same as above with IPlayerService.

My ultimate question is, how do I register PlayersController so it will properly inject IPlayersService with the correct sport? Assume my route looks like www.example.com/players/baseball.

This project is mainly to help me get more experience with Autofac, so it may be obvious I'm essentially a beginner with it.

2
  • Knowing and injecting the sport is not your DI container's responsibility. The sport is data, provided by a service. Injecting the service that provides that data is what your DI container should be concerned about. Oct 22, 2016 at 17:46
  • Yeah, that makes sense. Do you have an example of how you would set up your recommendation?
    – Matt
    Oct 23, 2016 at 11:59

1 Answer 1

1

Your composition root won't have any idea what kind of sport to pass, since it is part of the overall initialization and not executed as part of any user request. Presumably, however, your controller will know what sport, perhaps by sniffing the querystring, or using other contextual data that is passed in as part of the routing logic.

If this is the case, then here is your solution:

  1. Don't inject an IPlayerService. Instead, inject a IPlayerServiceFactory.
  2. Modify the controller so that it will use the factory to get an IPlayerService of the appropriate type, e.g.

    class MyController : Controller
    {
        private readonly IPlayerServiceFactory _playerServiceFactory;
    
        public MyController(IPlayerServiceFactory psf)
        {
            _playerServiceFactory = psf;
        }
    
        public ActionResult MyAction(string sportType)
        {
            IPlayerService playerService = _playerServiceFactory.GetService(sportType);
            //Do other stuff
            return View();
        }
    }
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.