如何在Blazor自定义验证属性类中使用依赖注入的服务?
在Blazor Hybrid中实现依赖注入的自定义验证属性
在Blazor Hybrid场景下,ValidationAttribute的实例是在属性标记时创建的,无法直接通过构造函数注入Scoped服务。解决这个问题的核心思路是利用验证时传入的ValidationContext获取服务提供者,从而拿到你需要的BusinessConstantsLookup实例。
解决方案:通过ValidationContext获取服务
直接在IsValid方法中从ValidationContext提取服务,这样既能符合Scoped服务的生命周期,又能获取到依赖的ILookupService实例。
1. 实现CustomRangeAttribute
public class CustomRangeAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 从ValidationContext中获取BusinessConstantsLookup实例 var constantsLookup = validationContext.GetService(typeof(BusinessConstantsLookup)) as BusinessConstantsLookup; if (constantsLookup == null) { return new ValidationResult("无法获取业务常量查询服务"); } // 从数据库获取验证所需的常量值(示例方法,根据你的实际逻辑调整) var allowedMin = constantsLookup.GetMinimumValidValue(); var allowedMax = constantsLookup.GetMaximumValidValue(); // 执行范围验证逻辑 if (value == null) { return ValidationResult.Success; // 根据业务需求决定是否允许null值 } if (value is int inputValue) { if (inputValue < allowedMin || inputValue > allowedMax) { return new ValidationResult($"输入值必须在{allowedMin}到{allowedMax}之间"); } } else { return new ValidationResult("输入值类型无效"); } return ValidationResult.Success; } }
2. 在模型中使用自定义验证属性
public class YourFormModel { [CustomRange] public int TargetProperty { get; set; } }
3. Blazor组件中正常使用表单验证
<EditForm Model="@formModel" OnValidSubmit="@HandleSubmit"> <DataAnnotationsValidator /> <ValidationSummary /> <InputNumber @bind-Value="@formModel.TargetProperty" /> <ValidationMessage For="@(() => formModel.TargetProperty)" /> <button type="submit">提交</button> </EditForm> @code { private YourFormModel formModel = new YourFormModel(); private void HandleSubmit() { // 处理表单提交逻辑 } }
关键注意事项
- 禁止在
ValidationAttribute的构造函数中获取Scoped服务:ValidationAttribute会被框架缓存为单例,直接在构造函数中注入Scoped服务会导致生命周期冲突(单例持有Scoped实例,无法正确释放)。 - 确保服务注册正确:确认
ILookupService和BusinessConstantsLookup已经在Main中完成Scoped注册:builder.Services.AddScoped<ILookupService, LookupService>(); builder.Services.AddScoped<BusinessConstantsLookup>();
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

