如何手动实现依赖注入?Dto类中ServiceProvider为空问题求助
在实现IValidatableObject的DTO中注入服务的解决方案
问题原因
DTO作为数据传输对象,通常由模型绑定器直接实例化,而非通过DI容器创建,因此:
- 自定义的
ServiceProvider字段不会被自动赋值 [FromServices]属性无法在DTO的方法中生效,框架不会处理该注入逻辑
可行解决方案
方案1:通过ValidationContext直接获取服务
在Validate方法中,利用传入的ValidationContext实例获取所需服务,无需额外定义字段:
public partial class Dto : IValidatableObject { public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { var results = new List<ValidationResult>(); // 从ValidationContext获取服务 var scService = validationContext.GetService(typeof(ISCService)) as ISCService; if (scService == null) { results.Add(new ValidationResult("无法获取ISCService服务")); return results; } // 调用服务并执行验证逻辑 var data = scService.GetData(); if (/* 验证不通过条件 */) { results.Add(new ValidationResult("验证失败的提示信息")); } return results; } }
方案2:使用异步验证(适用于异步服务方法)
如果服务方法是异步的(如GetIdAsync),实现IAsyncValidatableObject接口来进行异步验证:
public partial class Dto : IAsyncValidatableObject { public async Task<IEnumerable<ValidationResult>> ValidateAsync(ValidationContext validationContext, CancellationToken cancellationToken) { var results = new List<ValidationResult>(); var scService = validationContext.GetService(typeof(ISCService)) as ISCService; if (scService == null) { results.Add(new ValidationResult("无法获取ISCService服务")); return results; } var site = await scService.GetIdAsync(/* 传入待验证的ID参数 */); if (site == null) { results.Add(new ValidationResult("该ID不存在")); } return results; } }
方案3:自定义验证属性(拆分验证逻辑)
如果单个字段的验证需要服务,可以创建自定义ValidationAttribute,在属性内部通过ValidationContext获取服务:
public class IdExistsAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var scService = validationContext.GetService(typeof(ISCService)) as ISCService; if (scService == null) { return new ValidationResult("无法获取ISCService服务"); } var id = value as string; if (string.IsNullOrEmpty(id)) { return new ValidationResult("ID不能为空"); } // 同步服务方法调用示例 var site = scService.GetId(id); if (site == null) { return new ValidationResult("该ID不存在"); } return ValidationResult.Success; } }
在DTO中使用该属性:
public partial class Dto { [IdExists] public string Id { get; set; } }
注意:如果服务方法是异步的,自定义验证属性需要结合异步验证逻辑实现,建议优先使用
IAsyncValidatableObject方案。
内容的提问来源于stack exchange,提问作者Mukesh
相关产品推荐
相关产品推荐

