如何将我自己的类注入到 ASP.NET MVC Core 的控制器中?

Posted

技术标签:

【中文标题】如何将我自己的类注入到 ASP.NET MVC Core 的控制器中?【英文标题】:How do I inject my own classes into controllers in ASP.NET MVC Core? 【发布时间】:2017-08-03 15:18:12 【问题描述】:

我创建了自己的用户管理类UserManager。我希望控制器能够访问 UserManager 对象以登录或注册用户。

我知道我必须在控制器类中提供一个参数化构造函数,该构造函数接受 UserManager 的对象并将其分配给私有属性等。

但是在哪里如何在我的项目中注册我的类,以便它会被 ASP.NET MVC Core 框架自动注入?

【问题讨论】:

docs.microsoft.com/en-us/aspnet/core/fundamentals/… 没有冒犯,但你有没有尝试搜索这个? 是的,我发现了很多线程处理 MVC 而不是 MVC Core,或者像 @R.Richards 这样的文档发布了关于如何添加单例或接口的文章,所以我假设我正在查看错误的文档,因为我假设有一个我找不到的更简单的解决方案。 ASP.NET Core 无法停止谈论依赖注入。这是他们在发布时宣传的最重要的事情之一。如果你搜索 asp.net core 依赖注入或 asp.net core 中间件,有很多关于它的文档。 @problemofficer:我不想这么说。我是说有些东西在某些服务器上存在糟糕的文档,有些东西在你所看到的任何地方以及介于两者之间的任何地方都有婴儿证明的分步教程。据我了解,这个确切的用例严重倾向于婴儿防护端。如果我错了,那就这样吧。我的错,我接受。但我的理解是,找到这个答案几乎需要零努力,堆栈溢出指南要求在提出问题之前做出明确的努力。我没有看到这种努力。 【参考方案1】:

Startup.cs类的ConfigureServices(IServiceCollection services)方法中添加:

services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();

IOperationTransientIOperationScopedIOperationSingleton 替换为您自己需要注入的类/服务。

注册服务注入的三种方式:

    瞬态 - 每次请求时都会创建这些服务。 Scoped - 这些服务将为每个请求创建一次。 单例 - 这些服务在第一个请求时创建一次,然后每个后续请求都将收到相同的实例。

【讨论】:

这个答案不清楚,因为您使用的是接口,但没有解释原因。目前尚不清楚 IOperationTransient 与 UserManager 的关系。与此同时,我自己发现了它,但你的回答对此并没有真正的帮助。虽然 imo 确实很好地解释了这三种类型的服务。 你的问题是“但是我在哪里以及如何在我的项目中注册我的类,以便它会被 ASP.NET MVC Core 框架自动注入?”,我为你清楚地回答了这个问题。您的问题没有问“接口如何与类相关”。事实上,你已经问到在哪里注册服务,我认为你知道 DI 的原则。【参考方案2】:

注入依赖项的类通常不使用具体类 (UserManager.cs) 作为其构造函数参数,而是依赖于接口,例如IUserManager。虽然可以使用具体的类,但接口提供了更松散的耦合,这就是首先使用依赖注入的原因。

每当框架遇到“想要”接口的构造函数(在本例中为控制器的构造函数)时,它也会查找应该使用哪个具体类进行注入。

在哪里

Startup.csConfigureServices方法中定义了“类想要X类型”和“框架将用Y类型注入”之间的关系。

什么

1。决定创建对象的生命周期

定义上述关系共有三个选项,它们在依赖注入框架创建的对象的生命周期不同。

official documentation 说:

瞬态

每次请求时都会创建瞬态生命周期服务。 此生命周期最适合轻量级、无状态的服务。

作用域

范围内的生命周期服务为每个请求创建一次。

单例

单例生命周期服务在首次创建时创建 请求(或者如果您指定实例,则在运行 ConfigureServices 时 那里),然后每个后续请求都将使用相同的实例。

2。添加代码

选择生命周期后(范围在以下示例中),添加行

services.AddScoped<IInterfaceUsedByControllerParameter, ClassThatWillBeInjected>();

或用于 OPs 类

services.AddScoped<IUserManager, UserManager>();

或者如果UserManager 实现了多个接口:

services.AddScoped<ILogin, UserManager>();
services.AddScoped<IRegister, UserManager>();

当一个类需要具有这两个接口中的任何一个的构造函数参数时,通过这两行,依赖注入将为它提供一个UserManager类型的对象。

代码示例

如果是最后一个例子,UserManager 实现了接口ILoginIRegister

控制器

public class UserController : Controller
    
        private readonly ILogin    _login;
        private readonly IRegister _registration;

        public UserController(ILogin login, IRegister registration)
        
            _login = login;
            _registration = registration;
        
...
...

Startup.cs

 public void ConfigureServices(IServiceCollection services)
        
            ...
            services.AddScoped<ILogin, UserManager>();
            services.AddScoped<IRegister, UserManager>();
            ...
            services.AddMvc();
            ...

【讨论】:

在阅读了更多文档并(希望)了解了依赖注入的工作原理后,我决定自己添加一个答案。恕我直言,它更详细地解释了答案,更容易理解,最重要的是它解释了AddScoped 中的两个泛型参数如何相关或它们表达什么。也许这对像我一样不理解这个概念的其他人有用。

以上是关于如何将我自己的类注入到 ASP.NET MVC Core 的控制器中?的主要内容,如果未能解决你的问题,请参考以下文章

asp.net mvc 依赖注入有啥用

asp.net mvc 依赖注入有啥用

如何在 ASP.NET MVC 6 中注册 ILogger 以进行注入

如何在 ASP.NET Core MVC 中使用依赖注入设计存储库模式?

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

Controller.User 在 ASP.NET MVC 5 上由 ASP.NET Identity 设置不一致