.Net Core核心概念——依赖注入和中间件

这篇具有很好参考价值的文章主要介绍了.Net Core核心概念——依赖注入和中间件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

依赖注入的理解与应用

1. 为什么要用依赖注入(DI)

什么是依赖注入,为什么要使用呢?简单通俗说就是一个类需要另一个类来协助工作,就产生了依赖,所以需要的依赖项就要【注入】过来一起来协同完成工作。
软件设计原则中有一个依赖倒置原则(DIP)讲的是要依赖于抽象,不要依赖于具体,高层模块不应该依赖于低层模块, 二者应该依赖于抽象。简单的说就是为了更好的解耦。而控制反转(Ioc)就是这样的一个实现思路, 这个思路的其中一种实现方式就是依赖注入(DI)
感觉有点绕, 举个栗子:老李是一个维修工, 现在要出任务去维修, 得先去申领个扳手。
.Net Core核心概念——依赖注入和中间件
老李: “请给我一把可以拧7mm大小的六角螺丝的扳手.”, 然后库管老张就从仓库里拿了一把这样的大力牌扳手给老李。
在这个例子中, 维修工老李只要告诉库管我要一个 "可以拧7mm大小的六角螺丝"的扳手即可, 他不用关心扳手的品牌和样式, 也不用采购扳手,更不用关心这个扳手是怎么来的。而对于库管, 他只需提供满足这样规则的一个扳手即可, 不用去关心老李拿着这个扳手之后去干什么。所以老李和老张都只是关心"可以拧7mm大小的六角螺丝的"这个规则即可, 也就是说, 如果后期仓库里不再提供大力牌扳手, 而是提供了这样的大牛牌扳手, 无论换了什么牌子和样式, 只要仍满足这个规则, 老李仍然可以正常工作。它们定义了一个规则(比如接口IWrench7mm), 二者都依赖于这个规则, 然后仓库无论提供大力牌(WrenchDaLi : IWrench7mm)还是大牛牌(WrenchDaNiu : IWrench7mm), 都不影响正常工作.
 这就是依赖倒置原则(DIP), 不依赖于具体(牌子), 高层模块(老李)不应该依赖于低层模块(大力牌扳手), 二者应该依赖于抽象(IWrench7mm:可以拧7mm大小的六角螺丝)。如果直接由老李去获取(new)大力牌扳手, 那么当业务改变要求采用大牛牌的时候, 我们就要去修改老李的代码。为了解耦, 在本例中我们只要在配置中让仓库由原来的提供大力牌改为提供大牛牌即可。老李要使用的时候, 可以通过注入(构造器、属性、方法)的方式, 将仓库提供的扳手实例提供给老李使用。

2. 依赖注入理解

引入依赖注入的目的是为了解耦。说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用。
这样做的好处就是如果添加了另一个种实现类,不需要修改之前代码,只需要修改注入的地方将实现类替换。上面说的通过接口调用方法,实际上还是需要去实例化接口的实现类,只不过不需要我们手动new 构造实现类,而是交给如微软的DI、Autofac这些工具去构建实现类。我们只需要告诉它们,某个类是某个接口的实现类,当用到的时候,工具(比如,微软的DI)会自动通过构造函数实例化类。

3. 依赖的服务如何注入

打开Startup这个文件, 看一下里面的ConfigureServices方法。顾名思义, 这个方法是用来配置服务,系统默认已经添加了一些服务, 剩下的就是我们把自己需要的用的添加进去。参数为服务集合IServiceCollection对象,这种对象提供了AddSingleton、AddScoped和AddTransient 三种方法来添加服务,三种方法添加的服务的生命周期不一样。
实例:
添加一个名为DIDemo的.NET CORE MVC项目,在该项目下创建一个服务文件夹(Servers)
(1)定义接口ICount
.Net Core核心概念——依赖注入和中间件
(2)实现接口类Count
.Net Core核心概念——依赖注入和中间件
至此,服务(类)有了,那么如何能让这个服务为我们所用呢?或者说为我们服务呢?
(3)把类(服务)在Startup文件中通过ConfigureServices方法注入服务。
.NET Core 中自带的DI容器,可以理解为StartUp.CS文件。——不准确
使用容器的好处,由容器来统一管理实例的创建和销毁,你只需要关心怎么用就行了,不需要关系怎么创建跟销毁。
当然容器创建的实例都是有生命周期的。三种创建方法创建的实例生命周期不一样。

  • Transient: 瞬态模式,每一次访问都会创建一个新的实例
  • Scoped: 域模式,在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http
    request会在一个 scope内)。对象在一次请求中是相同的,但在不同请求中是不同的。
  • Singleton :单例模式,整个应用程序生命周期以内只创建一个实例 此外,常用注入方式有三种。
public void ConfigureServices(IServiceCollection services)
        {
           ……
            //下面先以AddScopend方法阐述下常用的三种注入方式
            //1.最常用的注入方式,以接口形式暴露服务。下面2中方式意思一样
            //1.1 AddScopend后面是(),里面的接口和实现类必须套一层typeof
            services.AddScoped(typeof(ICount), typeof(Count));
            //1.2 AddScopend后面是<>,里面就直接写接口和实现类,当然最后有一个()
            services.AddScoped<ICount, Count>();
            //2.自己注入自己,以实现形式暴露服务
            services.AddScoped(typeof(Count));
            services.AddScoped<Count>();
            //3.需要传参的构造函数的类的注入(后面实例有应用讲解)
            // services.AddScoped(typeof(ICount), sp => { return new Count(参数); }) ;
            //services.AddScoped<ICount>(sp => { return new Count(参数);}) ;
……
        }

(4)接下来分析演示三种注入方法的区别:
上面ConfigureServices方法中保留下面的瞬态模式
//第1种:瞬态模式,每一次访问都会创建一个新的实例

services.AddTransient<ICount, Count>();

服务注入之后,我们就要用它。切换到控制器。那么能把服务实例注入到控制器中来呢?有属性注入、构造方法注入、方法注入。这里一般会用构造方法注入。

public class HomeController : Controller
    {
        private ICount _count;//方便本类其他方法的调用,所以定义一个私有字段来接收
        public HomeController(ICount count)//通过构造方法注入实例,ASP.NET CORE内置了依赖注入容器
        {
            _count = count;
        }
        //说明:请求到home控制器,自然调用home控制器的构造方法,构造方法中需要一个ICount类型的对象,它怎么来的呢?这就是因为.NET Core内置了依赖注入容器,这个时候就会到StartUp.cs文件中的ConfigureServices方法中去找相应的依赖,而在那里告诉了ICount由Count来实现( services.AddTransient<ICount, Count>();),所以这时会去调用Count 的构造方法实例化Count对象。
        //接下来就可以在控制器中使用_count
        public IActionResult Index()
        {
            int c = _count.MyCount();
            ViewBag.count = c;
            return View();
        }

前端展示
.Net Core核心概念——依赖注入和中间件
运行效果,不断刷新页面也总是0,因为瞬态模式注入的服务,每一次访问都会创建一个新的实例。
.Net Core核心概念——依赖注入和中间件
上面ConfigureServices方法中改为下面的单例模式
//第2种:单例模式,整个应用程序生命周期以内只创建一个实例

services.AddSingleton<ICount, Count>();

.Net Core核心概念——依赖注入和中间件
运行效果,不断刷新页面不断增加1.
继续把上面ConfigureServices方法中改为下面的域模式
//第3种:域模式,在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)

services.AddScoped<ICount, Count>();

运行效果,不断刷新页面一直保持为0,因为每次刷新页面都是一个新的请求,所以总是0,在一个请求内产生的实例对象才是唯一。

改进下测试代码

public class HomeController : Controller
    {
        private IServiceProvider _provider;
        private ICount _count;//方便本类其他方法的调用,所以定义一个私有字段来接收
        public HomeController(ICount count,IServiceProvider provider)//通过构造方法注入实例,ASP.NET CORE内置了依赖注入容器
        {
            _count = count;
            _provider = provider;
        }
        //接下来就可以在控制器中使用_count
        public IActionResult Index()
        {
            //int c = _count.MyCount();
            //ViewBag.count = c;
            //注意导入using Microsoft.Extensions.DependencyInjection;
            ICount count1 = _provider.GetService<ICount>();
            ICount count2 = _provider.GetService<ICount>();
            int c1=count1.MyCount();
            int c2 = count2.MyCount();
            ViewBag.c1 = c1;
            ViewBag.c2 = c2;
            //ICount counter1 = _provider.GetService<ICount>();
            //ICount counter2 = _provider.GetService<ICount>();
            //int c1 = counter1.Get();
            //int c2 = counter2.Get();
            return View();
        }

.Net Core核心概念——依赖注入和中间件
测试发现c1、c2分别为0,1
但是每次刷新又重新为0,1
因为每次刷新页面都是一个新的请求,所以总是0,在一个请求内产生的实例对象才是唯一
.Net Core核心概念——依赖注入和中间件

4.如何在视图中直接使用依赖注入

如下图修改视图,主要是通过@inject去注入实例对象
@inject DIDemo.Services.ICount count
@{
int c = count.MyCount();
}
.Net Core核心概念——依赖注入和中间件
运行结果为2,原因是因为在控制器中生成的实例中已经得到0、1,而视图中的实例还是通过控制器注入时生成的那个实例,所以这个时候为2
.Net Core核心概念——依赖注入和中间件
如果在startup中是以瞬态模式注入,那么都是0,不断刷新也还都是0;如果是以单例模式注入,那么开始就是0 1 2,不断刷新就依次加1,即第一次刷新就变为3 4 5,再刷新就变为6 7 8

八、中间件的理解与初步应用

1. 中间件概念通俗理解

一个web应用程序都是把http请求封装成一个管道,一般来说每一次的请求都要先经过管道的一系列操作,最终到达我们写的代码(主程序)中。那么中间件就是在应用程序管道中的一个组件,用来拦截请求过程进行一些其他处理和响应(比如验证用户身份是否合法、程序中是否有异常等)。中间件可以有很多个,每一个中间件都可以对管道中的请求进行拦截,它可以决定是否将请求转移给下一个中间件。

简言之:中间件是用于组成应用程序管道来处理请求和响应的组件。与过滤器类似,都属于AOP应用。

在ASP.NET Core中,针对HTTP请求采用pipeline(管道)方式来处理,而管道容器内可以挂载很多中间件(处理逻辑)“串联”来处理HTTP请求,每一个中间件都有权决定是否需要执行下一个中间件,或者直接做出响应。这样的机制使得HTTP请求能够很好的被层层处理和控制,并且层次清晰处理起来方便。
那么,何时使用中间件呢?一般是在我们的应用程序当中和业务关系不大的一些需要在管道中做的事情可以使用,比如身份验证,Session存储,日志记录等。
微软官方的一个中间件管道请求图:
.Net Core核心概念——依赖注入和中间件
从上图可以看出除最后一个中间件外,每个中间件包含3部分,一个进入时处理逻辑,一个是调用next方法进入下一个中间件,一个是退出中间件的处理逻辑。
意思即是每个委托均可在下一个委托前后执行操作。
此外,委托还可以决定不将请求传递给下一个委托,这就是对请求管道进行短路。

2. 自定义中间件

每个中间件在构建后就是一个RequestDelegate委托对象。实例:在当前解决方案下创建一个.NET Core mvc项目,命名为MiddlewareDemo,然后在其中创建一个文件夹Middlewares,再在其中创建MyMiddleware类。

 public class MyMiddleware
    {
        //private IConfiguration _configuration;
        //第一步:
        private RequestDelegate _next;// using Microsoft.AspNetCore.Http;
        //加一个构造方法.构造方法第一个参数必须是RequestDelegate类型,表示为中间件类型,即是表示为下一个中间件。定义中间件时必须包含对下一个中间件的引用。
        public MyMiddleware(RequestDelegate next)
        {
            _next = next;//通过私有字段去接收下一个中间件的引用,因为我们在其他地方需要用这个下一个中间件next。这步是关键,必须的有,这个实现把中间件串联起来
            //_configuration = configuration;
        }
        //第二步增加Task InvokeAsync(HttpContext context)方法,方法名称固定为InvokeAsync,返回值为Task
        public async Task InvokeAsync(HttpContext context)
        {
            await context.Response.WriteAsync("test");
            await _next.Invoke(context);
        }
}

接下来在StartUp.cs文件的Configure方法中注入启用中间件。使用UseMiddleware方法注册:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseMiddleware<MyMiddleware>();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        } 

中间件管道在应用程序启动时构建,默认情况下,中间件的执行顺序根据Startup.cs文件中,在public void Configure(IApplicationBuilder app){} 方法中注册的先后顺序执行。
自定义中间件总结:

  • 自定义中间件类
    •构造方法带RequestDelegate(下一个中间件的引用) 参数
    •增加Task InvokeAsync(HttpContext context)方法
  • 注册启用中间件
    IApplicationBuilder.UseMiddleware()
    此外还可以使用 Run、Map 和 Use 扩展方法来注册启用中间件。
    app.Use(),IApplicationBuilder接口原生提供,注册等都用它。 Use不会主动短路整个HTTP管道,但是也不会主动调用下一个中间件,必须自行调用await next.Invoke(); 如果不使用这个方法去调用下一个中间件那么Use此时的效果其实和Run是相同的。
    app.Run() ,是一个扩展方法,它需要一个RequestDelegate委托,里面包含了Http的上下文信息,没有next参数,因为它总是在管道最后一步执行。Run方法会使得可以使管道短路,顾名思义就是终结管道向下执行不会调用next()委托,所以Run方法最好放在管道的最后来执行。
    app.Map(),也是一个扩展方法,类似于MVC的路由,用途一般是一些特殊请求路径的处理。Map可以根据提供的URL来路由中间件 。见下面例子(3)。
    (1)如果中间件的逻辑比较简单,可以不去创建一个类,直接用
IApplicationBuilder.Use(
           Func<RequestDelegate,RequestDelegate> middleware)
如:
app.Use(next =>
            {
                return context =>
                {
                    return Task.CompletedTask;
                };
            });

(2)终点中间件——Run方法
整个中间件流水线的最后一个中间件,使用IApplicationBuilder.Run注册。

app.Run(context =>
            {
                return Task.CompletedTask;
            });

(3)分支中间件——Map方法
根据决策逻辑确定后续执行路线,分支后不能再合并
//假设app端的请求均已api开头.下面的意思就表示请求是以api开头的就会进入MyMiddleware中间件,后续的中间件就不会执行。 .Map方法以路径作为决策

  app.Map("/api", builder => {
                builder.UseMiddleware<MyMiddleware>();
             });

测试,在默认地址后加入/api就会调用MyMiddleware中间件,从而显示test。
.Net Core核心概念——依赖注入和中间件
其实我们的 asp.net core项目中本身已经包含了很多个中间件。
如果想添加使用更多的中间件,通过NuGet包管理器引用安装Microsoft.AspNetCore.Diagnostics
.Net Core核心概念——依赖注入和中间件
修改 Startup 类中的 Configure() 方法添加中间件 app.UseWelcomePage

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //上面的代码在非开发环境时,UseExceptionHandler是第一个被加入到管道中的中间件,因为会捕获之后调用中出现的任何异常,然后跳转到设置的异常页/home/Error
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
          
            app.UseWelcomePage();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
         }

.Net Core核心概念——依赖注入和中间件文章来源地址https://www.toymoban.com/news/detail-479443.html

到了这里,关于.Net Core核心概念——依赖注入和中间件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • ASP.NET Core中间件记录管道图和内置中间件

    下图显示了 ASP.NET Core MVC 和 Razor Pages 应用程序的完整请求处理管道 中间件组件在文件中添加的顺序 Program.cs 定义了请求时调用中间件组件的顺序以及响应的相反顺序。该顺序对于安全性、性能和功能 至关重要。   内置中间件 原文 翻译 Middleware Description Order 中间件 描述 命

    2024年02月13日
    浏览(36)
  • 测试 ASP.NET Core 中间件

            正常情况下,中间件会在主程序入口统一进行实例化,这样如果想单独测试某一个中间件就很不方便,为了能测试单个中间件,可以使用 TestServer 单独测试。 这样便可以: 实例化只包含需要测试的组件的应用管道。 发送自定义请求以验证中间件行为。 这样测试

    2024年01月20日
    浏览(40)
  • .net core 中什么是中间件

    在 .NET Core 中,中间件(Middleware)是 ASP.NET Core 应用程序处理请求和响应的组件。中间件位于应用程序的请求处理管道中,它可以截获请求,执行一些逻辑,并将请求传递给下一个中间件或终止请求的执行。 中间件的主要作用是实现横切关注点,处理跨请求的功能和任务,例

    2024年01月17日
    浏览(40)
  • asp.net core中间件预防防止xss攻击

    上面实现思路是针对json序列化后的string字符串进行编码防止xss攻击 其他实现比如中间件、Action的AOP方法也是可以的,可以自己实现 主要是看web项目使用的是那个json序列化工具newtonsoft就用newtonsoft,system.text.json就用下面的那个

    2024年02月07日
    浏览(41)
  • 如何在 ASP.NET Core 配置请求超时中间件

    本文参考官方文档,使用Asp.net core 8.0 的最小API 模板项目,配置超时中间件。 超时中间件可用于所有类型的ASP.NET Core应用:最小 API、带控制器的 Web API、MVC 和 Razor Pages。请求超时的属性位于命名空间 Microsoft.AspNetCore.Http.Timeouts 中。 需要注意的是,当应用在调试模式下运行时

    2024年01月20日
    浏览(36)
  • .net 温故知新【17】:Asp.Net Core WebAPI 中间件

    到这篇文章为止,关于.NET \\\"温故知新\\\"系列的基础知识就完结了,从这一系列的系统回顾和再学习,对于.NET core、ASP.NET CORE又有了一个新的认识。 不光是从使用,还包括这些知识点的原理,虽然深入原理谈不上,但对于日常使用也够了,我想的是知其然,知其所以然。 在实际

    2024年01月18日
    浏览(34)
  • 1.ASP.NET Core中间件管道MAP的作用?

    简述: Map基于给定请求路径的匹配项来创建请求管道分支。可以针对不同的路径添加不同的中间件。 详解: 中间件是组装到应用程序管道中以处理请求和响应的软件组件。 每个组件都选择是否将请求传递给管道中的下一个组件,并可以在管道中调用下一个组件之前和之后执

    2024年02月17日
    浏览(33)
  • ASP.NET Core如何知道一个请求执行了哪些中间件?

    需要添加两个Nuget包分别是: Microsoft.AspNetCore.MiddlewareAnalysis 和 Microsoft.Extensions.DiagnosticAdapter ,前者是分析记录中间件核心代码实现后者是用来接收日志输出的,由于是用的DiagnosticSource方式记录日志,所以需要使用DiagnosticListener对象的SubscribeWithAdapter方法来订阅。 这个适配器

    2023年04月09日
    浏览(42)
  • ASP.NET Core 的 Web Api 实现限流 中间件

    Microsoft.AspNetCore.RateLimiting  中间件提供速率限制(限流)中间件。 它是.NET 7 以上版本才支持的中间件,刚看了一下,确实挺好用,下面给大家简单介绍一下: RateLimiterOptionsExtensions 类提供下列用于限制速率的扩展方法:​​​​​ 固定窗口限制器 滑动窗口限制器 令牌桶限

    2024年01月17日
    浏览(28)
  • asp.net core 一种基于token 和 Permission 的权限管理中间件示例

    asp.net core webapi 下面,想做一个过滤权限的Filter,配合token,对api做一个较为细粒度的权限控制, 该filter (PermissionFilter) 的作用是用户LoginUser.Permissions 列表中有 Key指定的权限才可以访问,没有则返回403 错误码。   1. 先上封装后的使用效果 说明:要求登录即可,不要求特定权限

    2024年02月05日
    浏览(99)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包