Search code examples
c#asp.net-mvcdependency-injectionservice-locator

Creating volatile interfaces instances - dependency injection vs service locator


The problem is i have 3 layer project: DataAccess dll and Presentation dll depends on Logic dll. In logic i have defined interfaces od IRepository, IMyIdentityUser etc. In DataAccess I'm using Microsoft Identity framework to registering new users with MyIdentityUser that inherits IdentityUser<Guid> and IMyIdentityUser interface. I am also using IoC container. Let's say I have in Presentation (MVC) layer method called 'Register' with argument 'RegisterViewModel viewModel' that is delegating registering logic to some class in Logic dll.

  public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = MyCore.Resolve<IMyIdentityUser>(); //this is service locator 
                                                          // antipattern and I want to get
                                                          // rid of this
            user.UserName = model.Email;
            user.Email = model.Email;


            var userManager = _userManager;


            var result = await userManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {
                var signInManager = _signInManager;

                await signInManager.SignInAsync(user, false, false);
                return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
        }


        return View(model);
    }

as you see I'm using Service locator to get new instance of MyIdentityUser. I don't want to create this as 'new MyIdentityUser()' because this forces me use tight coupling with DataAccess dll where MyIdentityUser is defined. Also, I don't want to have in constructor parameter IMyIdentityUser and forcing IoC container to create new user instance each time I'm creating MVC controller. I think I could use some kind of abstract factory like

interface IMyIdentityUserFactory
{
    IMyIdentityUser CreateNewUser(string name, string email); //any other better arguments?
       // not like registerViewModel because 
       // this view model should be defined in presentation logic
}

and passing it as argument to controller constructor (maybe in facade parameter with another logically connected parameters) but I'm not sure of this because it's generally the same as passing lonely IMyIdentityUser. Is there better way to do this?


Solution

  • Also, i dont want to have in constructor parameter IMyIdentityUser and forcing IoC container to create new user instance each time i'm creating MVC controller.

    Your premise is wrong from scratch.

    1. MVC controllers aren't stateful. Each request instantiates a MVC controller (well, if you read the #2 point here, you'll might argue that you can change this default behavior if you implement IControllerActivator!)
    2. IoC containers don't necessarily create a new instance of a given injected dependency: it depends on the component life-cycle. For example, Castle Windsor will provide you transient, singleton, per-request, per-thread, pooled and other life-cycles. Transient will be the only choice that will surely create an instance of a given injected dependency.

    Thus, based on your wrong assumptions, I would definitively go with constructor injection wherever you need a dependency. Or property injection, but it's not the first choice when implementing dependency injection, because usually property injections are optional.

    In the other hand, construction injection should be the way to go because every piece of code will be independent of others (less coupling) in terms of testability: you can automatically or manually instantiate a given class and also automatically or manually provide its dependencies.