The answer from Ramin is the correct answer. But I decided to go the other way, so I do not need to write adapters and adapter providers for many cases.
The idea is to wrap your specific string localizer in a service interface and get it from the validation attribute itself.
public class CPFAttribute: ValidationAttribute { public CPFAttribute() { } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { string cpf; try { cpf = (string)value; } catch (Exception) { return new ValidationResult(GetErrorMessage(validationContext)); } if (string.IsNullOrEmpty(cpf) || cpf.Length != 11 || !StringUtil.IsDigitsOnly(cpf)) { return new ValidationResult(GetErrorMessage(validationContext)); } return ValidationResult.Success; } private string GetErrorMessage(ValidationContext validationContext) { if (string.IsNullOrEmpty(ErrorMessage)) { return "Invalid CPF"; } ErrorMessageTranslationService errorTranslation = validationContext.GetService(typeof(ErrorMessageTranslationService)) as ErrorMessageTranslationService; return errorTranslation.GetLocalizedError(ErrorMessage); } }
Then the service can be created as:
public class ErrorMessageTranslationService { private readonly IStringLocalizer<SharedResource> _sharedLocalizer; public ErrorMessageTranslationService(IStringLocalizer<SharedResource> sharedLocalizer) { _sharedLocalizer = sharedLocalizer; } public string GetLocalizedError(string errorKey) { return _sharedLocalizer[errorKey]; } }
A service can be registered as single in the Startup class.
services.AddSingleton<ErrorMessageTranslationService>();
If you need to consider these verification attributes in another assembly, simply create an interface for this translation service, which can be referenced by all the verification attributes you created.
source share