简体   繁体   English

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

[英]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. 问题是我有3层项目: DataAccess dll和Presentation dll取决于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. 在逻辑上,我定义了IRepository, IMyIdentityUser等接口。在DataAccess中,我使用Microsoft Identity框架向继承了IdentityUser<Guid>IMyIdentityUser接口的MyIdentityUser注册新用户。 I am also using IoC container. 我也在使用IoC容器。 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. 假设我在Presentation(MVC)层中有一个名为' Register '的方法,其参数为' 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);
    }

as you see I'm using Service locator to get new instance of MyIdentityUser. 如您所见,我正在使用服务定位器来获取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. 我不想将其创建为“ new MyIdentityUser() ”,因为这迫使我与定义MyIdentityUser的DataAccess dll紧密耦合。 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. 另外,我不想每次创建MVC控制器时都在构造函数参数IMyIdentityUser强制使用IoC容器来创建新的用户实例。 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 . 并将其作为参数传递给控制器​​构造函数(也许在带有另一个逻辑连接参数的Facade参数中),但是我不确定,因为它通常与传递孤独的IMyIdentityUser相同。 Is there better way to do this? 有更好的方法吗?

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. 另外,我不希望每次创建MVC控制器时都在构造函数参数IMyIdentityUser中强制IoC容器创建新的用户实例。

Your premise is wrong from scratch. 您的前提是从头开始是错误的。

  1. MVC controllers aren't stateful. MVC控制器不是有状态的。 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 !) 每个请求都实例化一个MVC控制器(好吧,如果您在此处阅读了第二点,您可能会争辩说,如果实现IControllerActivator则可以更改此默认行为!)
  2. IoC containers don't necessarily create a new instance of a given injected dependency: it depends on the component life-cycle. IoC容器不一定会创建给定注入依赖性的新实例:它取决于组件的生命周期。 For example, Castle Windsor will provide you transient, singleton, per-request, per-thread, pooled and other life-cycles. 例如,Castle Windsor将为您提供瞬态,单例,按请求,按线程,池化和其他生命周期。 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. 另一方面,构造注入应该是可行的方法,因为在可测试性方面,每段代码都将彼此独立(较少耦合):您可以自动或手动实例化给定的类,还可以自动或手动提供其依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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