创建易失性接口实例 - 依赖注入与服务定位器

时间:2016-09-30 13:32:43

标签: c# asp.net-mvc dependency-injection service-locator

问题是我有3层项目:DataAccess dll和Presentation dll取决于Logic dll。在逻辑中,我定义了接口od IRepository, IMyIdentityUser等。在DataAccess中,我使用Microsoft Identity框架向MyIdentityUser注册继承IdentityUser<Guid>IMyIdentityUser接口的新用户。我也在使用IoC容器。 假设我有一个名为“Register”的Presentation(MVC)层方法,其参数为“RegisterViewModel viewModel”,它将注册逻辑委托给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);
    }

如您所见,我正在使用服务定位器来获取MyIdentityUser的新实例。我不想将其创建为“new MyIdentityUser()”,因为这会强制我使用与定义MyIdentityUser的DataAccess dll紧密耦合。 此外,我不希望在构造函数参数IMyIdentityUser中强制IoC容器在每次创建MVC控制器时创建新的用户实例。 我想我可以使用像

这样的抽象工厂
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
}

并将其作为参数传递给控制器​​构造函数(可能在facade参数中使用其他逻辑连接的参数)但我不确定这一点,因为它通常与传递孤独IMyIdentityUser相同。 有更好的方法吗?

1 个答案:

答案 0 :(得分:3)

  

另外,我不想在构造函数参数IMyIdentityUser和   每次我都强制IoC容器创建新的用户实例   创建MVC控制器。

你的前提从头开始是错误的。

  1. MVC控制器不具有状态。每个请求都实例化一个MVC控制器(如果你在这里读到#2点,你可能会认为如果你实现IControllerActivator就可以改变这个默认行为!) < / LI>
  2. IoC容器不一定要创建给定注入依赖项的新实例:它取决于组件的生命周期。例如,Castle Windsor将为您提供瞬态,单一,每请求,每线程,汇集和其他生命周期。 Transient将是唯一一个肯定会创建给定注入依赖项的实例的选择。
  3. 因此,根据您错误的假设,无论您需要依赖项,我都会明确地使用构造函数注入。或属性注入,但它不是实现依赖注入时的首选,因为通常属性注入是可选

    另一方面,构造注入应该是可行的方法,因为在可测试性方面,每一段代码都将独立于其他代码(较少耦合):您可以自动或手动实例化给定类,也可以自动或手动提供它的依赖。

相关问题