Как добавить введенные пользовательские атрибуты проверки во время выполнения с помощью Simple Injector?
Сначала я зарегистрировал свой пользовательский атрибут:
container.Register<ValidationAttribute, CustomValidationAttribute>();
Я создал пользовательский DataAnnotationsModelValidatorProvider:
public class CustomModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
private ValidationAttribute _customValidationAttribute;
public CustomModelValidatorProvider(
ValidationAttribute customValidationAttribute) : base()
{
_customValidationAttribute = customValidationAttribute;
}
protected override IEnumerable<ModelValidator> GetValidators(
ModelMetadata metadata, ControllerContext context,
IEnumerable<Attribute> attributes)
{
IList<Attribute> customAttributes = attributes.ToList();
// It will be added for each property of the model
customAttributes.Add(_customValidationAttribute);
IEnumerable<ModelValidator> validators =
base.GetValidators(metadata, context, customAttributes);
return validators;
}
}
Я зарегистрировал это в контейнере:
// Register Custom Model Validation Provider
container.Register<DataAnnotationsModelValidatorProvider, CustomModelValidatorProvider>();
Я также создал DependencyResolverModelValidatorProvider
чтобы получить поставщика для GetValidator
методы, позволяющие внедрять другие экземпляры области действия:
public class DependencyResolverModelValidatorProvider
: DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(
ModelMetadata metadata, ControllerContext context,
IEnumerable<Attribute> attributes)
{
return GetProvider().GetValidators(metadata, context);
}
private static DataAnnotationsModelValidatorProvider GetProvider()
{
return (DataAnnotationsModelValidatorProvider)
DependencyResolver.Current.GetService(
typeof(DataAnnotationsModelValidatorProvider));
}
}
И наконец я заменил текущий DataAnnotationsModelValidatorProvider
:
ModelValidatorProviders.Providers.Remove(
ModelValidatorProviders.Providers
.OfType<DataAnnotationsModelValidatorProvider>().First());
ModelValidatorProviders.Providers.Add(new DependencyResolverModelValidatorProvider());
Является ли это хорошим способом добавления пользовательских атрибутов проверки во время выполнения с помощью Simple Injector?
1 ответ
Прежде всего, вы не должны явно регистрировать атрибуты в контейнере, если вы хотите сделать это во время выполнения.
В DataAnnotaionsModelMetadataProvider вы должны использовать метод GetRegistration.
Я решаю это так:
1) Мой пользовательский провайдер метаданных модели
public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
private readonly Container container;
public CustomModelMetadataProvider(Container container)
{
this.container = container;
}
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
var dependentAttributeType = typeof(DependentAttribute);
foreach (var attribute in attributes.Where(i => Attribute.IsDefined(i.GetType(), dependentAttributeType)))
{
container.GetRegistration(attribute.GetType(), true).Registration.InitializeInstance(attribute);
}
return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
}
}
2) Например, пользовательский атрибут (знак DependentAttribute) для распознавания в поставщике метаданных модели.
[Dependent]
public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute, IClientValidatable
{
[Dependency]
public IResourceReader ResourceReader { get; set; }
public override bool IsValid(object value)
{
return base.IsValid(value);
}
public override string FormatErrorMessage(string name)
{
return ResourceReader.Get(ErrorMessageResourceName);
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ValidationType = "required",
ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};
}
}
3) Я регистрирую только мой провайдер метаданных модели при запуске в моем коде
ModelMetadataProviders.Current = new CustomModelMetadataProvider(container);
Это все.