我使用 Microsoft Unity 作为我的 IoC 容器。我有许多扩展类,它们为我的业务对象添加了有用的方法 这是我今天使用的代码:
public static class BusinessObjectExtensions
{
public static bool CanDoStuff(this BusinessObject obj)
{
var repository = BusinessHost.Resolver.Resolve<IRepository>();
var args = new EArgument { Name = obj.Name };
return repository.AMethod(obj.UserName, args);
}
}
有没有更好的方法来管理扩展类的依赖注入?
构造函数注入的事实上的默认依赖注入方式对于静态类是不可能的。可以使用如下所示的参数注入,但这不是一个非常干净的方法。
public static class BusinessObjectExtensions
{
public static bool CanDoStuff(this BusinessObject obj, IRepository repository)
{
var args = new EArgument { Name = obj.Name };
return repository.AMethod(obj.UserName, args);
}
}
您实际上应该尝试避免扩展方法,除非它们仅适用于内部数据(类本身的属性)或方法中提供的简单数据类型。您不应该在扩展方法中与其他依赖项进行交互。如果遵循此规则,则根本不需要使用 IoC 注入扩展类。
你为什么要这么做?
这将应用程序中的耦合提升到了极限,并且可能会让您的队友在使用扩展方法时感到非常困惑(他们必须记住每次使用该方法时都注入存储库)。
相反,创建一个单独的类并使用构造函数注入来注入
IRepository
实例:
public class StuffExecuter
{
private readonly IRepository _repository;
public StuffExecuter(IRepository repository)
{
_repository = repository;
}
public bool CanExecute(BusinessObject obj)
{
_repository.Add(obj.UserName, new EArgument
{
Name = obj.Name
});
}
}
这是在 ASP.NET Core 中使用 DI 扩展类的完整示例。
1。添加所需的 NuGet 包 确保您已安装所需的软件包:
dotnet 添加包 Microsoft.Extensions.DependencyInjection.Abstractions
2。创建扩展类 扩展类封装了服务注册以更好地组织。下面是 DependencyInjection 命名空间中名为 AddDependencyInjection 的类:
using Microsoft.Extensions.DependencyInjection;
using dumdum.Interface;
using dumdum.Model.DB;
using dumdum.Service.Implementation;
using dumdum.Service.Interface;
using Sieve.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace dumdum.DependencyInjection
{
public static class AddDependencyInjection
{
public static IServiceCollection AddDependencies(this IServiceCollection services)
{
// Database Context
services.AddDbContext<Context>(options =>
options.UseSqlServer(Environment.GetEnvironmentVariable("CodeXMinioService")));
// General Services
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped(typeof(IBaseService<,>), typeof(BaseService<,>));
services.AddScoped<ISieveProcessor, SieveProcessor>();
services.AddScoped<ISQLORMService, DapperORMService>();
// Business Logic Services
services.AddScoped<IUploadService, UploadService>();
services.AddScoped<IUserMaster, UserMasterService>();
// JWT Authentication
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("your_secret_key_here")),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
return services;
}
}
}
3.使用Program.cs中的扩展方法 扩展类到位后,DI 注册可以轻松包含在应用程序的主入口点中:
using dumdum.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddDependencies(); // Adding dependencies via extension method
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the middleware pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
服务封装:所有的服务注册都封装在AddDependency方法中,提高了可重用性和可维护性。 模块化方法:每种类型的服务(例如,DbContext、存储库、业务逻辑服务)都按逻辑分组。 JWT 身份验证:通过使用令牌验证参数配置 AddJwtBearer 来保护您的 API。
可扩展性:随着应用程序的增长,轻松向扩展方法添加更多服务。 代码组织:将 DI 逻辑与应用程序启动代码分开。 可测试性:通过提供集中的模拟服务位置来简化单元测试。