1.依赖注入步骤
步骤一:使用接口或基类将依赖关系实现抽象化。
//IMyDependency接口定义了WriteMessage方法
public interface IMyDependency
{
void WriteMessage(string message);
}
//MyDependency具体类实现了IMyDependency接口
public class MyDependency : IMyDependency
{
public void WriteMessage(string message)
{
Console.WriteLine($"MyDependency.WriteMessage Message: {message}");
}
}
步骤二:使用 builder.Services
提供的服务注册方法在内置的DI服务容器 IServiceProvider 中注册服务。
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
//创建WebApplicationBuilder类的实例
//builder已将 配置、日志记录和许多其它服务 添加到 DI 容器中。
var builder = WebApplication.CreateBuilder(args);
//调用Services返回IServiceCollection接口实例
//使用AddScoped服务注册方法(服务生存期是范围内的)注册IMyDependency服务和MyDependency具体类。
builder.Services.AddScoped<IMyDependency, MyDependency>();
var app = builder.Build();
步骤三:将服务注入到使用它的类的构造函数中。
public class Index2Model : PageModel
{
private readonly IMyDependency _myDependency;
public Index2Model(IMyDependency myDependency)
{
_myDependency = myDependency;
}
public void OnGet()
{
_myDependency.WriteMessage("Index2Model.OnGet");
}
}
2.使用扩展方法注册服务组
2.1内置服务组
约定使用单个 Add{GROUP_NAME}
扩展方法来注册一组相关服务。比如:AddRazorPages、AddControllers、AddControllersWithViews、AddDbContext 和 AddDefaultIdentity等等。
2.1自定义服务组
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.Configure<PositionOptions>(
builder.Configuration.GetSection(PositionOptions.Position));
builder.Services.Configure<ColorOptions>(
builder.Configuration.GetSection(ColorOptions.Color));
var app = builder.Build();
可以将相关的注册组移动到扩展方法以注册服务。
建议应用遵循在 Microsoft.Extensions.DependencyInjection 命名空间中创建扩展方法的Add{GROUP_NAME}
命名约定。
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;
}
}
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddConfig(builder.Configuration);
builder.Services.AddRazorPages();
var app = builder.Build();
3.服务生存期
生存期长度:单例生存期>范围内生存期>暂时生存期,所以从暂时或其它范围内生存期服务可以解析范围内生存期服务,从暂时或范围内生存期服务可以解析单例生存期服务。从具有较长生存期的其它服务解析服务将会引发异常。
生存期名称 | 服务注册方法 | 同一个范围 | 新范围 |
暂时(Transient) | AddTransient | 新实例 | 新实例 |
范围内(Scoped) | AddScoped | 同一个实例 | 新实例 |
单例(Singleton) | AddSingleton | 同一个实例 | 同一个实例 |
4.服务注册方法
以下任何服务注册方法都可用于注册同一服务类型的多个实现。
方法 | 自动 对象 释放 | 多种 实现 | 传递参数 |
---|---|---|---|
Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>() 示例: services.AddSingleton<IMyDep, MyDep>(); | 是 | 是 | 否 |
Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION}) 示例: services.AddSingleton<IMyDep>(sp => new MyDep()); services.AddSingleton<IMyDep>(sp => new MyDep(99)); | 是 | 是 | 是 |
Add{LIFETIME}<{IMPLEMENTATION}>() 示例: services.AddSingleton<MyDep>(); | 是 | 否 | 否 |
AddSingleton<{SERVICE}>(new {IMPLEMENTATION}) 示例: services.AddSingleton<IMyDep>(new MyDep()); services.AddSingleton<IMyDep>(new MyDep(99)); | 否 | 是 | 是 |
AddSingleton(new {IMPLEMENTATION}) 示例: services.AddSingleton(new MyDep()); services.AddSingleton(new MyDep(99)); | 否 | 否 | 是 |
MyService
定义两个构造函数参数:一个是 IMyDependency
,另一个是 IEnumerable<IMyDependency>
。
当使用 IMyDependency
类型调用时,第二个AddSingleton
会重写第一个AddSingleton
,所以 IMyDependency
是已注册的最后一个实现。
当使用 IEnumerable<IMyDependency>
类型调用时,第二个AddSingleton
会添加到第一个AddSingleton
,所以IEnumerable<IMyDependency>
表示所有已注册的实现。通过 IEnumerable<{SERVICE}>
解析服务时,服务按其注册顺序显示。
services.AddSingleton<IMyDependency, MyDependency>();
services.AddSingleton<IMyDependency, DifferentDependency>();
public class MyService
{
public MyService(IMyDependency myDependency,
IEnumerable<IMyDependency> myDependencies)
{
Trace.Assert(myDependency is DifferentDependency);
var dependencyArray = myDependencies.ToArray();
Trace.Assert(dependencyArray[0] is MyDependency);
Trace.Assert(dependencyArray[1] is DifferentDependency);
}
}
5.在应用启动时限时解析范围内服务
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IMyDependency, MyDependency>();
var app = builder.Build();
using (var serviceScope = app.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var myDependency = services.GetRequiredService<IMyDependency>();
myDependency.WriteMessage("Call services from main");
}
app.MapGet("/", () => "Hello World!");
app.Run();
6.框架提供的服务
下表列出了框架提供的服务的一小部分:
原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/csharp/aspnetcoremvc/14602.html