Blazor WebAssembly中FluentValidation注入DbContext的依赖解析异常问题
解决方案:Blazor WASM中Blazored.FluentValidation依赖DbContext的验证器注入问题
问题根源
Blazored.FluentValidation默认使用无参构造创建验证器实例,而你的自定义验证器依赖GymDbContext,DI容器无法自动将服务注入到验证器中,导致抛出"Unable to resolve service for type 'DbContext'"异常。
具体解决步骤
1. 自定义验证器工厂
实现IValidatorFactory接口,让验证器能从DI容器中获取实例:
using FluentValidation; using Microsoft.Extensions.DependencyInjection; public class ServiceProviderValidatorFactory : IValidatorFactory { private readonly IServiceProvider _serviceProvider; public ServiceProviderValidatorFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public IValidator<T> GetValidator<T>() { return _serviceProvider.GetService<IValidator<T>>(); } public IValidator GetValidator(Type type) { var validatorType = typeof(IValidator<>).MakeGenericType(type); return (IValidator)_serviceProvider.GetService(validatorType); } }
2. 注册DI服务
在Program.cs中完成DbContext、验证器和自定义工厂的注册:
// 注册DbContext工厂(Blazor WASM推荐用工厂模式管理DbContext生命周期) builder.Services.AddDbContextFactory<GymDbContext>(options => options.UseSqlite("Data Source=gym.db")); // 替换为你的数据库配置 // 注册自定义验证器 builder.Services.AddScoped<IValidator<YourModel>, YourModelValidator>(); // 注册自定义验证器工厂 builder.Services.AddScoped<IValidatorFactory, ServiceProviderValidatorFactory>(); // 配置Blazored.FluentValidation使用自定义工厂 builder.Services.AddBlazoredFluentValidation(config => { config.ValidatorFactoryType = typeof(ServiceProviderValidatorFactory); });
3. 编写带DbContext依赖的验证器
通过构造函数注入IDbContextFactory<GymDbContext>(避免长期持有DbContext实例),实现唯一性校验:
using FluentValidation; using Microsoft.EntityFrameworkCore; public class YourModelValidator : AbstractValidator<YourModel> { private readonly IDbContextFactory<GymDbContext> _dbContextFactory; public YourModelValidator(IDbContextFactory<GymDbContext> dbContextFactory) { _dbContextFactory = dbContextFactory; // 邮箱唯一性校验 RuleFor(x => x.Email) .NotEmpty() .EmailAddress() .MustAsync(async (email, cancellation) => { using var dbContext = _dbContextFactory.CreateDbContext(); return !await dbContext.Users.AnyAsync(u => u.Email == email, cancellation); }) .WithMessage("邮箱已存在"); // 手机号唯一性校验 RuleFor(x => x.PhoneNumber) .NotEmpty() .MustAsync(async (phone, cancellation) => { using var dbContext = _dbContextFactory.CreateDbContext(); return !await dbContext.Users.AnyAsync(u => u.PhoneNumber == phone, cancellation); }) .WithMessage("手机号已存在"); // PESEL唯一性校验 RuleFor(x => x.PESEL) .NotEmpty() .MustAsync(async (pesel, cancellation) => { using var dbContext = _dbContextFactory.CreateDbContext(); return !await dbContext.Users.AnyAsync(u => u.PESEL == pesel, cancellation); }) .WithMessage("PESEL已存在"); } }
关键注意点
- Blazor WASM中不要直接注入DbContext实例,必须用
IDbContextFactory创建短期实例,避免内存泄漏和上下文状态问题。 - 确保验证器和DbContext工厂都注册为
Scoped生命周期,和Blazor组件的生命周期匹配。
内容的提问来源于stack exchange,提问作者Ayes
相关产品推荐
相关产品推荐

