ASP.NET Core 中的 Dependency injection

这篇具有很好参考价值的文章主要介绍了ASP.NET Core 中的 Dependency injection。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

依赖注入(Dependency Injection,简称DI)是为了实现各个类之间的依赖控制反转(Inversion of Control,简称IoC )。
ASP.NET Core 中的Controller 和 Service 或者其他类都支持依赖注入。

依赖注入术语中,
Service 是一个为其他对象提供服务的类**。
Service 不是一个Web Service,与Web Service无关

Service的使用方法一般是:

  1. 在Main函数中注册Register到容器中,可以使用ASP.NET Core 内置的容器或者第三方容器,比如Autofac。
  2. 在注册过的类的构造函数中即可将其他依赖类当作入参Resolve
  3. 或者通过IServiceScopeFactory Resolve
  4. 容器负责Dispose

比如:
定义接口:

public interface IMyDependency
{
    void WriteMessage(string message);
}

定义实现类:

public class MyDependency : IMyDependency
{
    public void WriteMessage(string message)
    {
        Console.WriteLine($"MyDependency.WriteMessage Message: {message}");
    }
}

在Services容器中注册类:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IMyDependency, MyDependency>();
builder.Services.AddScoped<PageModel, IndexModel>();
var app = builder.Build();
app.Run();

使用构造函数Resolve依赖对象:

public class IndexModel : PageModel
{
    private readonly IMyDependency myDependency;

    public IndexModel(IMyDependency myDependency)
    {
        myDependency = myDependency;            
    }
}

这样不用在IndexModel 内部再new一个IMyDependency 类的对象,而是使用构造函数传入的对象。
而由容器来维护创建Service的对象的生命周期,这个过程叫做Resolve,对象共有3种生命周期:

  • Transient,每次Resolve的时候都重新创建,即使在同一个Http Reuest中。
  • Scoped,每次Http Reuest中,Resolve的时候重新创建,在该请求中不变。
  • Singleton,第一次Resolve的时候创建,后续Resolve都使用相同的对象。Singleton 的Service必须线程安全,因为所有线程都要用到,并且要考虑内存的用量。
    注意:不应该在Singleton Service中Resolve Scoped类型的对象,反过来可以,因为可能导致Scoped类型的对象无法dispose。

使用IServiceScopeFactory 实现Resolve依赖对象:

public class IndexModel : PageModel
{
    private readonly IServiceScopeFactory serviceScopeFactory;

    public IndexModel(IServiceScopeFactory serviceScopeFactory)
    {
        serviceScopeFactory = serviceScopeFactory;            
    }
    public DoSomething()
    {
        using (var scope = serviceScopeFactory .CreateScope())
        {
            // resolve a database connection
            var db = scope.ServiceProvider.GetService<IDatabaseConnection>();
            // do something with it
        }            
    }
}

注册一组Service,类似实现一个

builder.Host.UseSerilog();

需要写一个ServiceCollection的扩展类,然后在实现中注册相关的类:

namespace Microsoft.Extensions.DependencyInjection
{
    public static class MyConfigServiceCollectionExtensions
    {
        public static IServiceCollection AddConfig(
             this IServiceCollection services, IConfiguration config)
        {
            services.Configure<PositionOptions>(
                config.GetSection(PositionOptions.Position));
            services.Configure<ColorOptions>(
                config.GetSection(ColorOptions.Color));

            return services;
        }

        public static IServiceCollection AddMyDependencyGroup(
             this IServiceCollection services)
        {
            services.AddScoped<IMyDependency, MyDependency>();
            services.AddScoped<IMyDependency2, MyDependency2>();
            return services;
        }
    }
}

然后就可以这样注册了

builder.Services
    .AddConfig(builder.Configuration)
    .AddMyDependencyGroup();

如何设计项目中的依赖Service:

  • 应当避免有状态的,静态的类
  • 应当避免地App中创建全局对象,而应该使用singleton services。
  • 应当避免直接在service中初始化依赖的类,这样会增加耦合。
  • 应当保证service功能单一,以便测试。
  • 如果类中有大量的依赖注入,说明这个类的功能过于复杂,应当拆分,使其单一职责。

Service的Dispose:

  • Singleton类型的 Service 不应该添加Dispose方法,App结束进程时会自动dispose。
  • Scoped和Transient类型的Service 应该添加Dispose方法,容器会自动调用。

其余建议文章来源地址https://www.toymoban.com/news/detail-672176.html

  • 不支持 async/await 注入,因为C#不支持async构造函数。
  • 不直接在容器中持久保存数据。
  • 配置项应该使用options pattern
  • 不应该static访问service。
  • 尽量让DI工厂的操作:同步,快速。
  • 通在构造函数中注入的时候,不应该使用 service locator pattern
  • 配置service的时候不应该调用 BuildServiceProvider,而只应该在注册B service时需要resolve A service的时候才用。
  • 开启Scope validation,避免scoped service中使用singletons service。
  • container 直接resolve service,可能会导致内存泄露,比如:
static void TransientDisposablesWithoutDispose()
{
    var services = new ServiceCollection();
    services.AddTransient<ExampleDisposable>();
    ServiceProvider serviceProvider = services.BuildServiceProvider();

    for (int i = 0; i < 1000; ++ i)
    {
        _ = serviceProvider.GetRequiredService<ExampleDisposable>();
    }
    //1,000 个对象会被创建,serviceProvider 不dispose,这1000个对象就不dispose。
}

到了这里,关于ASP.NET Core 中的 Dependency injection的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • ASP.NET Core 中的 Razor Pages

    Razor Pages 是基于页面的 ASP.NET Core Web App 架构。 相比 MVC 模式,Razor Pages的生产效率更快。 Razer Pages 需要两个中间件: builder…Services.AddRazorPages 添加 Razor Pages services app.MapRazorPages 添加 Razor Pages endpoints .cshtml 与 .cshtml.cs 在最简单的页面中: 看起来与 MVC 的页面差不多,但特别之

    2024年02月09日
    浏览(25)
  • ASP.NET Core 中的 wwwroot 文件夹

    ASP.NET Core 中的 wwwroot 文件夹

    在本文中,我将讨论 ASP.NET Core 应用程序中的 wwwroot 文件夹。请阅读我们之前讨论过ASP.NET Core 请求处理管道的文章。在本文的最后,您将了解 wwwroot 文件夹及其需求以及如何在 ASP.NET Core 应用程序中进行配置。 ASP.NET Core 中的 wwwroot 文件夹是什么? 默认情况下,ASP.NET Core 应用

    2024年02月04日
    浏览(10)
  • ASP.NET Core 中的两种 Web API

    ASP.NET Core 有两种创建 RESTful Web API 的方式: 基于 Controller,使用完整的基于ControllerBase的基类定义接口endpoints。 基于 Minimal APIs,使用Lambda表达式定义接口 endpoints。 基于 Controller 的 Web API 可以使用构造函数注入,或者属性注入,遵循面向对象模式。 基于 Minimal APIs 的 Web API 通

    2024年02月09日
    浏览(14)
  • 安全机密管理:Asp.Net Core中的本地敏感数据保护技巧

    安全机密管理:Asp.Net Core中的本地敏感数据保护技巧

    在我们开发过程中基本上不可或缺的用到一些敏感机密数据,比如 SQL 服务器的连接串或者是 OAuth2 的 Secret 等,这些敏感数据在代码中是不太安全的,我们不应该在源代码中存储密码和其他的敏感数据,一种推荐的方式是通过 Asp.Net Core 的 机密管理器 。 在 ASP.NET Core 中,机密

    2024年04月25日
    浏览(15)
  • [Asp.Net Core] 网站中的XSS跨站脚本攻击和防范

    [Asp.Net Core] 网站中的XSS跨站脚本攻击和防范

    漏洞说明: 跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Web脚本代码(html、javascript、css等),当用户浏览该页面时,嵌入其中的Web脚本代码会被执行,从而达到恶意攻击

    2023年04月14日
    浏览(9)
  • Web SSH 的原理与在 ASP.NET Core SignalR 中的实现

    Web SSH 的原理与在 ASP.NET Core SignalR 中的实现

    有个项目,需要在前端有个管理终端可以 SSH 到主控机的终端,如果不考虑用户使用 vim 等需要在控制台内现实界面的软件的话,其实使用 Process 类型去启动相应程序就够了。而这次的需求则需要考虑用户会做相关设置。 这里用到的原理是伪终端。伪终端(pseudo terminal)是现

    2024年02月07日
    浏览(12)
  • ASP.NET和ASP.NET Core的区别

    ASP.NET和ASP.NET Core是两个不同的Web应用程序框架,它们都是由Microsoft开发的。ASP.NET是Microsoft推出的第一个Web应用程序框架,而ASP.NET Core是其最新版本。本文将介绍ASP.NET和ASP.NET Core的简介和区别。 ASP.NET的简介 ASP.NET是一个基于.NET框架的Web应用程序框架,它是Microsoft推出的第一

    2024年02月16日
    浏览(43)
  • ASP.NET Core教程:ASP.NET Core 程序部署到Windows系统

    ASP.NET Core教程:ASP.NET Core 程序部署到Windows系统

    本篇文章介绍如何将一个ASP.NET Core Web程序部署到Windows系统上。这里以ASP.NET Core WebApi为例进行讲解。首先创建一个ASP.NET Core WebApi项目,使用默认的Values控制器,这里使用Visual Studio 2019创建一个ASP.NET Core 3.1d的WebApi项目。 创建新项目的时候选项ASP.NET Core Web应用程序,如下图所

    2023年04月08日
    浏览(42)
  • Asp.Net VS ASP.NET Core 请求管道

    Asp.Net VS ASP.NET Core 请求管道

    参考链接 ASP.NET CORE 启动过程及源码解读 请求进入Asp.Net工作进程后,由进程创建HttpWorkRequest对象,封装此次请求有关的所有信息,然后进入HttpRuntime类进行进一步处理。HttpRuntime通过请求信息创建HttpContext上下文对象,此对象将贯穿整个管道,直到响应结束。同时创建或从应用

    2024年02月04日
    浏览(43)
  • ASP.NET Core MVC -- 将视图添加到 ASP.NET Core MVC 应用

    ASP.NET Core MVC -- 将视图添加到 ASP.NET Core MVC 应用

    右键单击“视图”文件夹,然后单击“添加”“新文件夹”,并将文件夹命名为“HelloWorld”。 右键单击“Views/HelloWorld”文件夹,然后单击“添加”“新项”。 在“添加新项 - MvcMovie”对话框中: 在右上角的搜索框中,输入“视图” 选择“Razor 视图 - 空” 保持“名称”框的

    2024年02月13日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包