8 依赖关系链我们通过一个例子来了解一下依赖链,例如:如果一个alpha的组件有依赖于一个beta的组件,然而beta组件又依赖于另外一个组件gamma,这就形成了一个依赖链,ASP.NET Core 能够很好的解析这个依赖链,让我们通过一个例子来了解在Models文件夹下添加一个新的接口IStorage.cs,定义如下:
namespace AspNetCore.DependencyInjection.Models
{
public interface IStorage
{
IEnumerable<Product> Items { get; }
Product this[string key] { get; set; }
bool ContainsKey(string key);
void RemoveItem(string key);
}
}
接下来创建一个新的Storage类继承该接口
namespace AspNetCore.DependencyInjection.Models
{
public class Storage : IStorage
{
private Dictionary<string, Product> items = new Dictionary<string, Product>();
public Product this[string key]
{
get { return items[key]; }
set { items[key] = value; }
}
public IEnumerable<Product> Items => items.Values;
public bool ContainsKey(string key)
{
return items.ContainsKey(key);
}
public void RemoveItem(string key)
{
items.Remove(key);
}
}
}
这个Storage类针对Product对象定义了一个简单存储机制,现在我们进入Repository类,在构造函数中创建一个IStorage接口的依赖,代码如下:
namespace AspNetCore.DependencyInjection.Models
{
public class Repository : IRepository
{
private IStorage _storage;
public Repository(IStorage storage)
{
_storage = storage;
new List<Product> {
new Product { Name = "Women Shoes", Price = 99M },
new Product { Name = "Skirts", Price = 29.99M },
new Product { Name = "Pants", Price = 40.5M }
}.ForEach(p => AddProduct(p));
}
public IEnumerable<Product> Products => _storage.Items;
public Product this[string name] => _storage[name];
public void AddProduct(Product product) => _storage[product.Name] = product;
public void DeleteProduct(Product product) => _storage.RemoveItem(product.Name);
private string guid = Guid.NewGuid().ToString();
public override string ToString()
{
return guid;
}
}
}
现在所有方法和属性将使用IStorage对象工作,在这里我们创建一个依赖链:
1 HomeController类依赖于IRepository对象
2 IRepository对象依赖于IStorage对象现在我们告诉ASP.NET Core 服务如何解析依赖链,因此进入Program.cs类,添加下面代码
var builder = WebApplication.CreateBuilder(args);
//builder.Services.AddTransient<IRepository, Repository>();
//builder.Services.AddScoped<IRepository, Repository>();
//builder.Services.AddSingleton<IRepository,Repository>();
builder.Services.AddTransient<ProductSum>();
builder.Services.AddTransient<IRepository, Repository>();
builder.Services.AddTransient<IStorage, Storage>();
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
重新运行你的应用程序你将看到有所有的产品将显示在浏览器中
9 在Programe类中获取服务我们可以通过下面代码在Programe类中获取服务
10 Action方法中获取服务通过Controller构造函数声明依赖是非常昂贵的,我们可以通过在请求的方法中获取服务我们将添加一个[FromServices] 特性在action方法中指定它依赖的服务我们进入HomeController修改Index,使用[FromServices]从方法中获取ProductSum服务, 把ProductSum从构造函数中移除
代码如下:
namespace AspNetCore.DependencyInjection.Controllers
{
public class HomeController : Controller
{
private IRepository _repository;
public HomeController(IRepository repository)
{
_repository = repository;
}
public IActionResult Index([FromServices] ProductSum _productSum)
{
ViewBag.HomeControllerGUID = _repository.ToString();
ViewBag.TotalGUID = _productSum.Repository.ToString();
return View(_repository.Products);
}
}
}
当Index方法调用时解析ProductSum类型,不在Controller构造时解析
11 ASP.NET Core 工厂方法注入
我们可以使用工厂模式来注册服务,因此你可以使用它创建你自己的逻辑告诉应用程序如果解析依赖,在Models文件夹下创建一个新的类ProductionRepository.cs,代码如下:
namespace AspNetCore.DependencyInjection.Models
{
public class ProductionRepository : IRepository
{
private Dictionary<string, Product> products;
public ProductionRepository()
{
products = new Dictionary<string, Product>();
new List<Product> {
new Product { Name = "Women Shoes", Price = 99M },
new Product { Name = "Skirts", Price = 29.99M },
new Product { Name = "Pants", Price = 40.5M }
}.ForEach(p => AddProduct(p));
}
public IEnumerable<Product> Products => products.Values;
public Product this[string name] => products[name];
public void AddProduct(Product product) => products[product.Name] = product;
public void DeleteProduct(Product product) => products.Remove(product.Name);
}
}
现在我们在开发环境和生产环境中分别注册不同的服务,我们通过函数代理并且添加lambda函数创建
12 把JSON文件注入应用程序我们可以使用依赖注入将JSON文件注入到Controller或者View,让我们展示一下如何指定这个工作在项目根目录创建一个JSON文件命名为mysettings.json, 将下面内容添加到JSON文件中:
{
"Title": "Dependency Injection Tutorial",
"Version": 3
}
针对这个JSON文件创建一个类,在Models文件夹下创建一个MyJson.cs类
public class MyJson
{
public string Title { get; set; }
public int Version { get; set; }
}
接下来配置应用程序从JSON文件读取到类,因此在你的应用程序中添加下面代码
using DependencyInjection.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("mysettings.json",
optional: false, //file is not optional
reloadOnChange: true);
});
builder.Services.Configure<MyJson>(builder.Configuration);
var app = builder.Build();
现在可以从任何Controller或者View中读取JSON文件的值,因此我们创建一个Controller并命名为SettingsController.cs,在这个控制器中添加构造函数并且添加IOptions<MyJson>类型的参数, 这个参数通过依赖注入的技术提供JSON文件中的值,代码如下:
using DependencyInjection.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace DependencyInjection.Controllers
{
public class SettingsController : Controller
{
private readonly MyJson _settings;
public SettingsController(IOptions<MyJson> settingsOptions)
{
_settings = settingsOptions.Value;
}
public IActionResult Index()
{
ViewData["Title"] = _settings.Title;
ViewData["Version"] = _settings.Version;
return View();
}
}
}
我们将这两个值显示到视图中,因此在Views->Settings文件加下添加Index视图,并在视图中添加如下代码:
@if (ViewData.Count > 0)
{
<table class="table table-bordered table-sm table-striped">
@foreach (var kvp in ViewData)
{
<tr><td>@kvp.Key</td><td>@kvp.Value</td></tr>
}
</table>
}
运行应用程序,你将会看到值显示到页面上
13 View中获取依赖注入对象
使用@inject指令可以在ASP.NET Core View 中使用依赖注入,我们通过两个例子来了解:
13.1 将JSON文件注入到View前面我们介绍了依赖注入JSON文件的值到控制器中,这次我将注入mysettings.json文件值到View中,在前面我们已经在Program.cs类中做配置
在SettingsController中添加一个新的Show方法
public IActionResult Show()
{
return View();
}
接下来添加名为Show.cshtml的View和下面代码
@using Microsoft.Extensions.Options;
@using AspNetCore.DependencyInjection.Models
@inject IOptions<MyJson> settingsOptions
<table class="table table-bordered table-sm table-striped">
<tr>
<td>Title</td>
<td>@settingsOptions.Value.Title</td>
</tr>
<tr>
<td>Version</td>
<td>@settingsOptions.Value.Version</td>
</tr>
</table>
注意:通过下面代码显示JSON的值
运行程序输入URL-https://localhost:7206/Settings/Show, 你将看到值显示在View
13.2 appsettings.json注入View
我们可以将appsettings.json文件的值注入的view,这个过程非常简单,你只需要使用inject指令然后显示他们的值,代码如下:
@inject IConfiguration Configuration
<div>@Configuration["Logging:LogLevel:Default"]</div>
我们将下面appsettings.json文件的值显示到页面
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
我们将显示Default,Microsoft.AspNetCore节点的值,在SettingsController中添加Detail方法
public IActionResult Detail()
{
return View();
}
在Detail视图中添加如下代码
@inject IConfiguration Configuration
<table class="table table-bordered table-sm table-striped">
<tr>
<td>Default</td>
<td>@Configuration["Logging:LogLevel:Default"]</td>
</tr>
<tr>
<td>Microsoft</td>
<td>@Configuration["Logging:LogLevel:Default"]</td>
</tr>
<tr>
<td>Microsoft.Hosting.Lifetime</td>
<td>@Configuration["Logging:LogLevel:Microsoft.AspNetCore"]</td>
</tr>
</table>
显示页面
总结
这节中我们主要讲解了如何在ASP.NET Core中使用依赖注入,以及依赖注入对象的方法,以及使用不同方法注入时对象的生命周期,在Programe和Action方法以及View中获取依赖注入的服务
源代码地址
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Fundamentals/AspNetCore.DependencyInjection/AspNetCore.DependencyInjection参考文献[1]https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-7.0
[2]https://www.yogihosting.com/aspnet-core-configurations/#content-generating-middleware
声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/79189.html