我正在尝试使用 IoC 容器将服务注入验证类。请参阅以下示例:
[Validator(typeof(UserPayloadValidator))]
public class UserPayload
{
public int UserId { get; set; }
}
public class UserPayloadValidator : AbstractValidator<UserPayload>
{
private IUserService _userService;
public UserPayloadValidator(IUserService userService)
{
_userService = userService;
RuleFor(x => x.UserId).Must(BeUnique).WithMessage("This user already exists");
}
private bool BeUnique(int userId)
{
var user = _userService.GetUser(userId);
return user == null;
}
}
在这一点上,我希望一切都能自动神奇地工作,并且userService将被注入到验证类中。相反,我收到一个异常,抱怨找不到无参数构造函数。
经过一些重新搜索,我尝试创建一个验证工厂,如链接的示例所示。
public class LightInjectValidationFactory : ValidatorFactoryBase
{
private readonly ServiceContainer _serviceContainer;
public LightInjectValidationFactory(ServiceContainer serviceContainer)
{
_serviceContainer = serviceContainer;
}
public override IValidator CreateInstance(Type validatorType)
{
return _serviceContainer.TryGetInstance(validatorType) as IValidator;
}
}
和在 LightInject 配置中
//Set up fluent validation
FluentValidationModelValidatorProvider.Configure(httpConfiguration, provider =>
{
provider.ValidatorFactory = new LightInjectValidationFactory(container);
});
这会导致异常:无法解析类型:FluentValidation.IValidator'1
我猜 IoC 容器不知道如何解析验证器的正确实例。
任何想法都非常感谢。
多亏了上面的评论,我意识到我实际上并没有在容器中注册验证器。对于所有验证器,这可以像这样完成:
FluentValidation.AssemblyScanner.FindValidatorsInAssemblyContaining<UserPayloadValidator>()
.ForEach(result =>
{
container.Register(result.InterfaceType, result.ValidatorType);
});
请注意,UserPayloadValidator
只需要是您的验证者之一。基于此类型,FindValidatorsInAssembly 可以推断所有其他可用的验证器。
此外,在验证工厂中,您应该使用 TryGetInstance 而不是 GetInstance,以防工厂尝试实例化不存在的验证器(控制器中不存在验证器的参数)
我找到了所有使用注入服务的验证类的解决方案。
替换以下代码
FluentValidation.AssemblyScanner.FindValidatorsInAssemblyContaining<UserPayloadValidator>()
.ForEach(result =>
{
container.Register(result.InterfaceType, result.ValidatorType);
});
跟
FluentValidation.AssemblyScanner findValidatorsInAssembly = FluentValidation.AssemblyScanner.FindValidatorsInAssembly(typeof(UserPayloadValidator).Assembly);
foreach (FluentValidation.AssemblyScanner.AssemblyScanResult item in findValidatorsInAssembly)
{
container.Register(item.InterfaceType, item.ValidatorType);
}
使用它,您的所有验证器类都使用注入的服务。