这实际上是
how to get the instance decorated by an attribute, from the attribute
(类似问题
here
)
不幸的是,简短的回答是:你不能。
属性
是
元数据。属性不知道和
不能
了解它所修饰的类或成员的任何信息。由类的一些下游使用者来查找所述自定义属性并决定是否/何时/如何应用它们。
你必须把属性想成
数据
不是
物体
. 尽管属性在技术上是类,但它们相当愚蠢,因为它们有一个关键的约束:关于它们的所有内容都必须在编译时定义。这实际上意味着他们无法访问任何运行时信息,
除非
它们公开采用运行时实例的方法
和
调用方决定调用它。
你可以做后者。您可以设计自己的属性,只要控制验证器,就可以让验证器对该属性调用一些方法,并让它执行几乎所有操作:
public abstract class CustomValidationAttribute : Attribute
{
// Returns the error message, if any
public abstract string Validate(object instance);
}
只要任何人正确使用这个类的属性,这将起作用:
public class MyValidator
{
public IEnumerable<string> Validate(object instance)
{
if (instance == null)
throw new ArgumentNullException("instance");
Type t = instance.GetType();
var validationAttributes = (CustomValidationAttribute[])Attribute
.GetCustomAttributes(t, typeof(CustomValidationAttribute));
foreach (var validationAttribute in validationAttributes)
{
string error = validationAttribute.Validate(instance);
if (!string.IsNullOrEmpty(error))
yield return error;
}
}
}
如果你是这样
消费
这些属性可以很容易地实现您自己的:
public class PasswordValidationAttribute : CustomValidationAttribute
{
public override string Validate(object instance)
{
ChangePasswordModel model = instance as ChangePasswordModel;
if (model == null)
return null;
if (model.NewPassword != model.ConfirmPassword)
return Resources.GetLocalized("PasswordsDoNotMatch");
return null;
}
}
这一切都很好,只是控制流与您在原始问题中指定的相反。该属性不知道它应用于什么;验证程序
使用
属性必须提供该信息(它很容易做到)。
当然,这不是验证在MVC 2中如何与数据注释一起实际工作的(除非在我上次查看它之后它发生了显著的变化)。我想你不能把这个插上
ValidationMessageFor
以及其他类似的功能。但是,在MVC1中,无论如何我们都必须编写我们自己的验证器。没有什么能阻止您将DataAnnotations与您自己的自定义验证属性和验证器组合在一起,它只会涉及更多的代码。在编写验证代码的任何地方都必须调用特殊的验证程序。
这可能不是您要寻找的答案,但不幸的是,它是这样的;除非验证程序本身提供了该信息,否则验证属性无法知道它应用到的类。