抽象类中的依赖注入,ASP.NET Core

Posted

技术标签:

【中文标题】抽象类中的依赖注入,ASP.NET Core【英文标题】:Dependency Injection in abstract class, ASP.NET Core 【发布时间】:2018-09-13 03:10:27 【问题描述】:

在我的 ASP.NET Core 2 项目中,我创建了继承 RazorPage 类的新类,以在视图中添加一些额外的属性。

public abstract class WebViewPage<TModel> : Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>

    public string Version
    
        get
        
            return "1.00.100";
        
    
    public User CurrentUser
    
        get
        
            //challenge is here:
            //return _services.GetRequiredService<IUserService>().GetCurrentUser();
        
    


public abstract class WebViewPage : WebViewPage<dynamic>



_ViewImport.cshtml 文件更改为:

@inherits MyProject.WebViewPage<TModel>
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

在挑战代码被标记为评论之前,该项目运行良好。但是,如何将依赖项注入抽象类?或者如何解析抽象类中的服务?

这是我的StartUp.cs 文件:

public void ConfigureServices(IServiceCollection services)

        services.AddMemoryCache();
        services.AddMvc();
        services.AddTransient<IUserService, UserService>();
        //services.AddScoped<IRazorPage<?>, WebViewPage<?>(); // ?: challenge!

【问题讨论】:

我想你可以创建一个构造函数来请求依赖项,就像你可以对任何类做的那样?你试过吗? 你不能实例化抽象类,因此你不能用它来注册。你总是必须使用 concrete @Tseng 您对 DI 不适用于抽象类的评论有参考吗? @JayJayJay:C#(或一般的 OOP)基础知识。 abstract class。你想如何实例化抽象类?它只提供了一个基本的实现。要实例化它,您需要一个从基类继承的 concrete 类型/实现。因此,您需要一个一个地注册派生类。 .NET Core 的 DI (Microsoft.Extensions.DependencyInjection) 不像其他 IoC 容器那样支持程序集或类型扫描,因此您不能在一次调用中注册“所有从 Y 派生的类型”。您必须使用反射、一些 LINQ(或 for/foreach 循环)来过滤它,然后在循环中注册派生类型。内置 IoC 旨在简单且开箱即用,您可以插入具有扩展功能的 3rd 方容器(例如从 Y 派生的扫描或自动注册类型) 【参考方案1】:

如果您需要访问剃须刀页面内的服务提供商,您可以通过Context property 访问HttpContext,例如:

var userService = Context.RequestServices.GetRequiredService<IUserService>();

一个可能更好的选择是有一个将IUserService 作为依赖的构造函数。因此,您的类型的实现必须传递该依赖项,本质上要求它们自己具有构造函数依赖项(这是一个很好的显式设计)。


至于依赖注册部分,注意你一般不能注册抽象类,因为它们不能被实例化。

但一般来说,为了注册泛型类型,您必须使用更详细的 AddScoped 重载,它采用实际的 Type 参数:

services.AddScoped(typeof(IRazorPage<>), typeof(WebViewPage<>)); 

进行泛型方法调用需要一个真实类型作为泛型类型参数,因此您必须在IRazorPage&lt;T&gt;WebViewPage&lt;T&gt; 中为类型参数T 指定具体类型。由于您明确不想在此处使用具体类型,而是希望告诉依赖注入容器支持 any 类型,因此您不能在此处使用此语法。

由于typeof 运算符可以确定实际的通用 类型,您可以使用它而无需使用将注册限制为单一类型的特定类型参数。

【讨论】:

如何回答如何将服务注入 WebViewPage?其实我觉得不需要在容器中加入WebViewPage @CamiloTerevinto 我理解 OP,因为他们不知道如何注册 WebViewPage 作为他们的实现,因为他们显示的 Startup 中的注释行。 我明白真正的问题在于“//挑战在这里://return _services.GetRequiredService().GetCurrentUser();”这就是我对这个问题发表评论的原因 谢谢,但在这个问题中,我可以访问 Context,因为它在 RazorPage 类中定义! 是的,通过注入它们。不,如果这就是您的意思,(按设计)没有访问服务的静态方式。

以上是关于抽象类中的依赖注入,ASP.NET Core的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入

ASP.NET Core Web 应用程序系列- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)

[ASP.NET Core 3框架揭秘] 依赖注入:一个Mini版的依赖注入框架

理解ASP.NET Core

ASP.NET Core使用编译时依赖关系注入(DI)

ASP.NET Core 依赖注入基本用法