The ServiceCollection Extension Pattern
摘要
IServiceCollection 接口代表了一系列服务描述符的契约,提供了一个用于添加、删除和检索服务的抽象。
背景
在 .NET 环境中,依赖注入(DI)是一种基本的技术,帮助我们创建灵活、可测试和松耦合的代码。
它是控制反转(IoC)原则的一个实例,创建对象的控制由容器或框架管理,而不是由类本身管理。
IServiceCollection 接口代表了一系列服务描述符的契约,提供了一个用于添加、删除和检索服务的抽象。
这个接口在 Program.cs 类中变得非常重要。
在这里,我们注入了应用程序所需的所有必要服务。
ServiceCollection 扩展模式
在较大的应用程序中,Program.cs 可能会变得臃肿和混乱。
为了避免这种情况,我们可以利用一种称为ServiceCollection 扩展模式的模式。
这种模式让我们将服务注册逻辑封装到单独的静态类中,提供一个更有条理和可读的结构。
这种模式涉及在 IServiceCollection 接口上创建扩展方法。
让我们看一个例子:
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddCustomServices(
this IServiceCollection services)
{
services.AddScoped<IMyService, MyService>();
services.AddSingleton<IOtherService, OtherService>();
// ... 其他服务
return services;
}
}
然后在你的 Program.cs 文件中,你可以这样利用这些扩展方法:
builder.Services.AddCustomServices();
真实世界的例子
我们可以进一步使用这种模式对我们的服务进行分类,例如,为不同类型或层次的服务创建不同的扩展方法。
让我们考虑一个使用 Entity Framework Core 进行数据访问,Identity 进行身份验证和授权,并且还需要配置 CORS(跨域资源共享)的应用程序。
以下是你在这种场景下如何应用 ServiceCollection 扩展模式的示例。
数据库:
public static IServiceCollection AddDatabase(
this IServiceCollection services,
string connectionString)
{
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
return services;
}
身份验证:
public static IServiceCollection AddIdentityServices(
this IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<MyDbContext>()
.AddDefaultTokenProviders();
return services;
}
JWT 身份验证:
public static IServiceCollection AddJwtAuthentication(
this IServiceCollection services, IConfiguration configuration)
{
var jwtSettings = configuration.GetSection("JwtSettings");
var key = Encoding.ASCII.GetBytes(jwtSettings.GetValue<string>("Secret"));
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
return services;
}
Cors 策略:
public static IServiceCollection AddCorsPolicy(
this IServiceCollection services,
string policyName,
string[] allowedOrigins)
{
services.AddCors(options =>
{
options.AddPolicy(policyName,
builder => builder.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
return services;
}
然后在你的 Program.cs 文件中,你可以这样利用这些扩展方法:
builder.Services.AddDatabase(Configuration.GetConnectionString("DefaultConnection"));
builder.Services.AddIdentityServices();
builder.Services.AddJwtAuthentication(Configuration);
builder.Services.AddCorsPolicy("MyPolicy", new[] { "http://example.com" });
// ... 其他配置