使用ASP.NET MVC,是否可以将构造函数注入与数据注释属性一起使用(具体来说,我使用的是验证属性)?
我希望能做的是:
public class NoEmailTakenAttribute : ValidationAttribute
{
public NoEmailTakenAttribute(IService service) { .. }
}
这可能吗?
感谢。
答案 0 :(得分:3)
你不能使用我在Reflector中看到的控制器注入,但它似乎可以使用属性注入。通过创建一个继承自DataAnnotationsModelValidatorProvider
的类,并通过覆盖方法GetValidators
,似乎可以在验证发生之前将属性注入到属性中......这是从初始分析开始的,完全确定。
答案 1 :(得分:0)
您可以通过为IService接口创建基本控制器类和声明属性并使用参数IService写入基本控制器类来完成此操作。在派生类中使用它。 由于asp.net mvc使用默认的控制器构造函数来初始化您的服务由派生类参数化构造函数实例化的时间。
答案 2 :(得分:0)
我认为没有一种简单的方法可以为自定义数据注释进行构造函数注入甚至属性注入。 @BrianMains的建议听起来似乎有道理,但我自己并没有走得那么远。
解决复杂问题的一种方法是在自定义数据注释中使用服务定位器来获取您需要的任何依赖项。不是很干净,但会得到相同的结果。
查看此链接以获取更多信息:Dependency injection in custom DataAnnotations in ASP.Net MVC 3
答案 3 :(得分:0)
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));
你应该好好去。这里唯一的问题是您的验证器也将由默认机制创建。显然这会导致验证器没有注入适当的依赖项。我不知道如何从默认创建中排除验证器,但如果您正确检查验证器中的空值,它应该可以正常工作(我必须说一些解决方法,但也许你会找到更好的方法)。
答案 4 :(得分:0)
Brian Mains answer是正确的,但太简短了。所以这是一个例子。
首先定义一个提供程序
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 answer。 对于Web Api(How To Add Custom ModelValidatorProviders To Web API Project? )
config.Services.Add(typeof(ModelValidatorProvider), new CustomProvider());