【问题标题】:Dependency Injection in abstract class, ASP.NET Core抽象类中的依赖注入,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 派生的扫描或自动注册类型)

标签: c# asp.net-core razor-pages


【解决方案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 类中定义!
  • 是的,通过注入它们。不,如果这就是您的意思,(按设计)没有访问服务的静态方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-01
  • 2019-12-03
  • 2018-01-16
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多