.NET Core依赖注入中如何注入Unity示例中的验证类?
在.NET Core中实现Unity风格的构造注入替代方案
首先需要明确:.NET Core原生DI没有Unity那样的命名注册+直接指定构造注入参数的原生语法,我们可以通过两种方式实现你要的效果,具体取决于你的.NET版本:
第一步:确保目标类的构造函数依赖正确
你的Customer和Lead类需要接收对应的验证类作为构造参数,示例实现如下:
public class Customer : ICustomer { private readonly IValidation<ICustomer> _validator; // 构造函数注入验证类 public Customer(IValidation<ICustomer> validator) { _validator = validator; } // 实现ICustomer的属性 public string CustomerName { get; set; } public string PhoneNumber { get; set; } public decimal BillAmount { get; set; } public DateTime BillDate { get; set; } public string Address { get; set; } // 调用验证类的逻辑 public void Validation() { _validator.Validate(this); } } public class Lead : ICustomer { private readonly IValidation<ICustomer> _validator; public Lead(IValidation<ICustomer> validator) { _validator = validator; } // 实现ICustomer的属性 public string CustomerName { get; set; } public string PhoneNumber { get; set; } public decimal BillAmount { get; set; } public DateTime BillDate { get; set; } public string Address { get; set; } public void Validation() { _validator.Validate(this); } }
方法一:.NET 8及以上推荐使用Keyed服务
.NET 8新增了Keyed服务特性,可以直接为同接口的不同实现标记区分键,完美替代Unity的命名注册逻辑:
服务注册代码
var builder = WebApplication.CreateBuilder(args); // 1. 注册带Key的验证类 builder.Services.AddKeyedScoped<IValidation<ICustomer>, CustomerValidationAll>("CustomerValidator"); builder.Services.AddKeyedScoped<IValidation<ICustomer>, LeadValidation>("LeadValidator"); // 2. 注册Customer和Lead,指定注入对应Key的验证类 builder.Services.AddScoped<Customer>(sp => new Customer(sp.GetRequiredKeyedService<IValidation<ICustomer>>("CustomerValidator"))); builder.Services.AddScoped<Lead>(sp => new Lead(sp.GetRequiredKeyedService<IValidation<ICustomer>>("LeadValidator"))); // 3. 注册工厂函数,模拟Unity的Resolve<T>(name)逻辑 builder.Services.AddScoped<Func<string, ICustomer>>(sp => customerType => { return customerType switch { "Customer" => sp.GetRequiredService<Customer>(), "Lead" => sp.GetRequiredService<Lead>(), _ => throw new ArgumentException($"不支持的客户类型:{customerType}") }; });
使用方式
在需要获取实例的地方注入Func<string, ICustomer>即可:
public class DemoService { private readonly Func<string, ICustomer> _customerFactory; public DemoService(Func<string, ICustomer> customerFactory) { _customerFactory = customerFactory; } public void TestValidation() { // 获取Customer实例(已注入CustomerValidationAll) ICustomer customer = _customerFactory("Customer"); customer.CustomerName = ""; try { customer.Validation(); // 会触发完整验证 } catch (Exception ex) { Console.WriteLine(ex.Message); } // 获取Lead实例(已注入LeadValidation) ICustomer lead = _customerFactory("Lead"); lead.PhoneNumber = ""; try { lead.Validation(); // 仅触发姓名和手机号验证 } catch (Exception ex) { Console.WriteLine(ex.Message); } } }
方法二:.NET 7及以下版本的实现方式
低版本没有Keyed服务,我们可以直接注册验证类的具体类型,再在构造目标类时指定依赖:
服务注册代码
var builder = WebApplication.CreateBuilder(args); // 1. 注册验证类的具体类型 builder.Services.AddScoped<CustomerValidationAll>(); builder.Services.AddScoped<LeadValidation>(); // 2. 注册Customer和Lead,直接注入对应验证类 builder.Services.AddScoped<Customer>(sp => new Customer(sp.GetRequiredService<CustomerValidationAll>())); builder.Services.AddScoped<Lead>(sp => new Lead(sp.GetRequiredService<LeadValidation>())); // 3. 同样注册工厂函数 builder.Services.AddScoped<Func<string, ICustomer>>(sp => customerType => { return customerType switch { "Customer" => sp.GetRequiredService<Customer>(), "Lead" => sp.GetRequiredService<Lead>(), _ => throw new ArgumentException($"不支持的客户类型:{customerType}") }; });
使用方式
和方法一完全一致,注入Func<string, ICustomer>后根据类型字符串获取实例即可。
内容的提问来源于stack exchange,提问作者QueenBee
相关产品推荐
相关产品推荐

