翼度科技»论坛 编程开发 .net 查看内容

【ASP.NET Core】在 Mini-API 中注入服务

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
经过版本更新,Mini API 的功能逐步完善,早期支持得不太好的 mini API 现在许多特性都可以用了,比如灰常重要的依赖注入。
咱们先来个相当简单的注入测试。来,定义一个服务类,为了偷懒,老周这里就不使用 接口 + 实现类 的方式了。
  1. public class MyService : IDisposable
  2. {
  3.     public MyService()
  4.     {
  5.         Console.WriteLine($"{nameof(MyService)} 隆重开业");
  6.     }
  7.     public void Dispose()
  8.     {
  9.         Console.WriteLine($"{nameof(MyService)} 即将散伙");
  10.     }
  11.     public void DoSomething()
  12.     {
  13.         Console.WriteLine("正忙着呢……别闹");
  14.     }
  15. }
复制代码
此服务类提供给外部调用的公共方法是 DoSomething。
接下来在容器中注册一下这个服务。
  1. var builder = WebApplication.CreateBuilder(args);
  2. builder.Services.AddScoped<MyService>();
  3. var app = builder.Build();
复制代码
毕竟,每个 Web API 的调用都是一次消息往返,所以我选择将服务类注册为范围级别的——请求上下文的范围内存活。
最简单好用的注入方式是让服务类的实例通过参数传入。
  1. app.MapGet("/", (MyService sv) =>
  2. {
  3.     // 调用服务类的公共方法
  4.     sv.DoSomething();
  5.     return "三日成精五日成魔七日成鬼";
  6. });
复制代码
Web API 测试可以不使用第三方工具,dotnet tool 集合有个叫 httprepl 的工具,可以方便使用。此工具需要安装,命令如下:
  1. dotnet tool install -g microsoft.dotnet-httprepl
复制代码
安装完成后,直接在命令终端输入 httprepl ,回车。就进入了会话模式。假设应用程序的地址是 https://localhost:7249,可以用 connect 命令建立连接。
  1. connect https://localhost:7249
复制代码
发起请求时,可以用 get、post、put 等命令,对应 HTTP 的请求方式。在上面的例子中,咱们用的是 MapGet 方法注册的 API,相对路径是 /。
  1. get /
复制代码
调用成功后会返回文本。

而且,MyService 服务也被调用了。

 
接下来咱们改一下代码,添加一个参数x。
  1. app.MapGet("/", (int x, MyService sv) =>
  2. {
  3.     sv.DoSomething();
  4.     return $"你提交的参数是:{x}";
  5. });
复制代码
在调用 httprepl 工具时,也可以直接将 URL 作为命令行参数传给它,能省去使用 connect 命令。
  1. httprepl https://localhost:7249
复制代码
然后调用一下 API 。
  1. get /?x=150
复制代码
得到的响应如下:

 
从上面的改动可以知道:来自依赖注入的参数能够被识别。当然,咱们也可以明确指定各个参数的来源。
  1. app.MapGet("/", ([FromQuery]int x, [FromServices]MyService sv) =>
  2. {
  3.     sv.DoSomething();
  4.     return $"你提交的参数是:{x}";
  5. });
复制代码
再次运行,再次发出请求。
  1. get /?x=399
复制代码

 
注入服务在 POST 请求中也可以和作不 body 的参数一起用,例如:
  1. app.MapPost("/send", (Pet p, MyService sv) =>
  2. {
  3.     // 调用服务
  4.     sv.DoSomething();
  5.     string s = string.Format("宠物ID:{0},大名叫{1}", p.ID, p.Name);
  6.     // 返回文本
  7.     return s;
  8. });
复制代码
参数 sv 是依赖注入自动赋值的,而参数 p 是 Pet 实例,由HTTP请求的 body 部分提供(默认识别 JSON 格式)。Pet 类定义如下:
  1. public class Pet
  2. {
  3.     public int ID { get; set; }
  4.     public string? Name { get; set; }
  5. }
复制代码
这个类结构很简单,两个成员,用来测试的,不用在意。
在 HttpRepl 工具中可以用 post /send -h content-type=application/json -c ... 的格式提交,-h 指定 HTTP 头,-c 指定 body 部分。但是,在命令行中用 -c 参数指定 body 很难写,而且老容易出错。最好的做法是配置一个文本编辑器。在编辑器中输入好内容,保存关闭文件,然后 httprepl 工具会自动提交。编辑的文件是临时文件,由工具生成,我们不用管它,只要在输入好内容后保存就行。
文本编辑器用啥都行,如记事本。当然,最好设置 VS Code。操作如下:
先进入 httprepl 会话:
  1. httprepl
复制代码
接着配置 editor.command.default 参数:
  1. pref set editor.command.default "C:\Users\Bug-PC\tools\VSCode\Code.exe"
复制代码
设置项名称后面是 VS Code 的路径。然后,它会提示你最好加上 -w 参数,于是输入执行:
  1. pref set editor.command.default.arguments "-w"
复制代码
-w 参数是可以等待 VS Code 响应——等它编辑完关闭后返回 httprepl 工具。
现在,在 httprepl 会话中用 connect 命令连接服务器。
  1. connect https://localhost:7249
复制代码
发送 POST 请求。
  1. post /send -h content-type=application/json
复制代码
注意 Content Type 是 JSON 数据。执行后会启动 VS Code,然后我们输入:
  1. {
  2.     "id": 1234,
  3.     "name": "Jack"
  4. }
复制代码
完成后记得保存文件,并关闭 VS Code。关闭 VS Code 后回到 httprepl 会话,请求自动发送。

 
如果 mini-API 没有定义接收注入的参数,也可以用 HttpContext 来主动请求服务实例。请看下面代码:
  1. app.MapGet("/", (HttpContext context) =>
  2. {
  3.     // 主动请求服务
  4.     MyService sv = context.RequestServices.GetRequiredService<MyService>();
  5.     sv.DoSomething();
  6.     return "我在这里等了你上万年了!";
  7. });
复制代码
只要在所绑定的委托/方法中提供 HttpContext 类型的参数,就可以自动注入。随后在方法体中就可以直接引用。
这里要注意:此处咱们不能用 app.Services 去请求服务,因为它引用的是根容器(应用程序最开始创建的),不能访问生生命周期为 Scoped 的服务。
我们尝试把服务注册为单实例,看能不能用 app.Services 来获取。
  1. var builder = WebApplication.CreateBuilder(args);
  2. builder.Services.AddSingleton<MyService>();
  3. var app = builder.Build();
  4. app.MapGet("/", () =>
  5. {
  6.     // 主动请求服务
  7.     MyService sv = app.Services.GetRequiredService<MyService>();
  8.     sv.DoSomething();
  9.    
  10.     return "我在这里等了你上万年了!";
  11. });
复制代码
运行程序后,在 httprepl 中用 get / 命令测试通过。这说明,单例服务是支持通过 app.Services 获取的。不过,MyService 实例要等到应用程序结束时才会释放。
 

来源:https://www.cnblogs.com/tcjiaan/archive/2023/10/04/17742167.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具