使用 ASP.NET MVC,是否可以将构造函数注入与数据注释属性一起使用(具体来说,我正在使用验证属性)?
我想做的是:
public class NoEmailTakenAttribute : ValidationAttribute
{
public NoEmailTakenAttribute(IService service) { .. }
}
那可能吗?
谢谢。
使用 ASP.NET MVC,是否可以将构造函数注入与数据注释属性一起使用(具体来说,我正在使用验证属性)?
我想做的是:
public class NoEmailTakenAttribute : ValidationAttribute
{
public NoEmailTakenAttribute(IService service) { .. }
}
那可能吗?
谢谢。
从我使用 Reflector 看到的内容中,您不能使用控制器注入,但似乎可以使用属性注入。通过创建一个继承自的类DataAnnotationsModelValidatorProvider
,并覆盖方法GetValidators
,在验证发生之前属性可以被注入到属性中似乎是合理的......这是来自初步分析,尚未完全确定。
Brian Mains 提出的解决方案应该可以正常工作。我不认为构造函数注入是一个选项,但属性注入会完成这项工作。您可以从中派生ModelValidatorProvider
并且您的实现可能与此类似:
public class MyModelValidatorProvider : ModelValidatorProvider
{
private IDiContainer _container;
public MyModelValidatorProvider(IDiContainer container)
{
_container = container;
}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
List<ModelValidator> validators = new List<ModelValidator>();
PropertyInfo targetProperty = metadata.ContainerType.GetProperty(metadata.PropertyName);
if (targetProperty.GetCustomAttributes(false).Any(attr => attr.GetType() == typeof(NoEmailTakenAttribute)))
{
DataAnnotationsModelValidator<NoEmailTakenAttribute> validator = new DataAnnotationsModelValidator<NoEmailTakenAttribute>(
metadata, context, _container.Resolve<NoEmailTakenAttribute>());
validators.Add(validator);
}
return validators;
}
}
我没有仔细研究ModelMetadata
,只是使用 refelction 来决定是否返回验证器,但它可能可以做得更好。
然后在Global.asax
添加以下内容:
ModelValidatorProviders.Providers.Add(new MyModelValidatorProvider(InstanceOfContainer));
你应该很高兴。这里唯一的问题是您的验证器也将由默认机制创建。显然,这将导致您的验证器没有注入正确的依赖项。我不知道如何从默认创建中排除验证器,但是如果您正确检查验证器中的空值,它应该可以正常工作(我必须说一些解决方法,但也许您会找到更好的方法)。
您可以通过创建基本控制器类并为 IService 接口声明属性并使用参数 IService 编写基本控制器类来做到这一点。在派生类中使用它。由于 asp.net mvc 使用默认控制器构造函数来初始化您的服务被派生类参数化构造函数实例化的时间。
我认为没有一种简单的方法可以为自定义数据注释进行构造函数注入甚至属性注入。@BrianMains 的建议听起来很合理,但我自己并没有走那么远。
解决复杂性的一种方法是在自定义数据注释中使用服务定位器来获取您需要的任何依赖项。不那么干净,但可以得到相同的结果。
查看此链接以获取更多信息:ASP.Net MVC 3 中自定义 DataAnnotations 中的依赖注入
Brian Mains 的回答是正确的,但有点太简短了。所以这里有一个例子。
首先定义一个提供者
public class CustomProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, IEnumerable<ModelValidatorProvider> validatorProviders, IEnumerable<Attribute> attributes)
{
foreach (var attrib in attributes)
{
//if the attrib is your one set whatever you need
}
return base.GetValidators(metadata, validatorProviders, attributes);
}
}
然后注册它 - 对于 MVC,请参阅dmusial 答案。对于 Web Api(如何将自定义 ModelValidatorProviders 添加到 Web API 项目? )
config.Services.Add(typeof(ModelValidatorProvider), new CustomProvider());