ASP.NET中如何为自定义DataAnnotation注入依赖对象?
解决自定义DataAnnotation依赖注入的问题
在ASP.NET Core中,直接给自定义ValidationAttribute添加带依赖的构造函数确实行不通,因为属性注解要求无参构造。这里提供两种实用的解决思路:
方法一:在Validate方法中通过ValidationContext获取依赖
修改你的CheckForGenderAndBatchAttribute,不在构造函数中注入IBatchRepository,而是在Validate方法里通过ValidationContext的GetService方法获取所需服务:
public class CheckForGenderAndBatchAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 从ValidationContext中获取IBatchRepository实例 var batchRepo = validationContext.GetService(typeof(IBatchRepository)) as IBatchRepository; if (batchRepo == null) { return new ValidationResult("无法获取批次仓库服务"); } // 获取当前Coach模型实例,拿到性别信息 var coach = validationContext.ObjectInstance as Coach; if (coach == null) { return ValidationResult.Success; } int batchId = (int)value; var batch = batchRepo.GetById(batchId); // 假设仓库实现了该查询方法 if (batch == null) { return new ValidationResult("指定批次不存在"); } // 执行校验规则:男性教练不能分配至女性专属批次 if (coach.Gender == Gender.Male && batch.IsFemaleOnly) { return new ValidationResult("男性教练无法分配至女性专属批次"); } return ValidationResult.Success; } }
之后直接在Coach模型的BatchId属性上标记该注解即可:
public class Coach { public int Id { get; set; } public Gender Gender { get; set; } [CheckForGenderAndBatch] public int BatchId { get; set; } public Batch Batch { get; set; } }
关键前提:确保IBatchRepository及其实现类已注册到DI容器,比如在Program.cs中添加:
builder.Services.AddScoped<IBatchRepository, BatchProjectDbRepository>();
方法二:改用IValidatableObject接口
如果不想自定义Attribute,也可以让Coach模型实现IValidatableObject接口,直接在模型内编写校验逻辑,同样通过ValidationContext获取依赖:
public class Coach : IValidatableObject { public int Id { get; set; } public Gender Gender { get; set; } public int BatchId { get; set; } public Batch Batch { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { var batchRepo = validationContext.GetService(typeof(IBatchRepository)) as IBatchRepository; if (batchRepo == null) { yield return new ValidationResult("无法获取批次仓库服务"); yield break; } var batch = batchRepo.GetById(BatchId); if (batch == null) { yield return new ValidationResult("指定批次不存在", new[] { nameof(BatchId) }); yield break; } if (Gender == Gender.Male && batch.IsFemaleOnly) { yield return new ValidationResult("男性教练无法分配至女性专属批次", new[] { nameof(BatchId) }); } } }
这种方式更灵活,无需额外定义Attribute,适合校验逻辑与模型绑定较紧密的场景。
内容的提问来源于stack exchange,提问作者Sagar Tube
相关产品推荐
相关产品推荐

