Asp.net mvc 3 MVC3验证属性:在反射中丢失;一般分类

Asp.net mvc 3 MVC3验证属性:在反射中丢失;一般分类,asp.net-mvc-3,generics,reflection,data-annotations,Asp.net Mvc 3,Generics,Reflection,Data Annotations,我正在尝试为我的MVC3项目编写一个NotAttributevalidator属性。我想这样使用它: [Not("00000000-0000-0000-0000-000000000000", typeof(Guid), ErrorMessage = "You must select a valid id.")] public Guid ObjectId { get; set; } public class NotAttribute : ValidationAttribute, IClientV

我正在尝试为我的MVC3项目编写一个
NotAttribute
validator属性。我想这样使用它:

[Not("00000000-0000-0000-0000-000000000000", typeof(Guid), ErrorMessage = "You must select a valid id.")]
public Guid ObjectId { get; set; }
public class NotAttribute : ValidationAttribute, IClientValidatable
{
    public Type PropertyType { get; set; }
    public string NotEqualTo { get; private set; }
    public bool IgnoreWhitespace { get; set; }
    public bool CaseInsensitive { get; set; }

    public NotAttribute(string notEqualTo)
    {
        NotEqualTo = notEqualTo;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (PropertyType == null) PropertyType = typeof(string);
        if (PropertyType == typeof(string))
        {
            //this is the easy case.  We can compare easy enough
            var leftSide = value.ToStringOrEmpty();
            var rightSide = NotEqualTo ?? string.Empty;

            if (IgnoreWhitespace)
            {
                leftSide = leftSide.Trim();
                rightSide = rightSide.Trim();
            }

            if (CaseInsensitive)
            {
                leftSide = leftSide.ToUpperInvariant();
                rightSide = rightSide.ToUpperInvariant();
            }

            if (leftSide != rightSide) return null; // all is well
        }

        var tryParseMethod = PropertyType.GetMethod("TryParse",
            Reflection.BindingFlags.Static | Reflection.BindingFlags.Public, null,
            new Type[] {typeof(string), PropertyType.MakeByRefType()}, null);

        //This is where I get lost


        return base.IsValid(value, validationContext);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        throw new NotImplementedException();
    }
}
现在我不想将
NotAttribute
绑定到
Guid
,但是应该可以从字符串解析对象;我想先寻找
TryParse
方法,然后是
Parse
方法;如果两者都失败,并且类型还不是字符串,我想抛出一个错误。到目前为止,一切顺利,没有并发症

我的班级是这样的:

[Not("00000000-0000-0000-0000-000000000000", typeof(Guid), ErrorMessage = "You must select a valid id.")]
public Guid ObjectId { get; set; }
public class NotAttribute : ValidationAttribute, IClientValidatable
{
    public Type PropertyType { get; set; }
    public string NotEqualTo { get; private set; }
    public bool IgnoreWhitespace { get; set; }
    public bool CaseInsensitive { get; set; }

    public NotAttribute(string notEqualTo)
    {
        NotEqualTo = notEqualTo;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (PropertyType == null) PropertyType = typeof(string);
        if (PropertyType == typeof(string))
        {
            //this is the easy case.  We can compare easy enough
            var leftSide = value.ToStringOrEmpty();
            var rightSide = NotEqualTo ?? string.Empty;

            if (IgnoreWhitespace)
            {
                leftSide = leftSide.Trim();
                rightSide = rightSide.Trim();
            }

            if (CaseInsensitive)
            {
                leftSide = leftSide.ToUpperInvariant();
                rightSide = rightSide.ToUpperInvariant();
            }

            if (leftSide != rightSide) return null; // all is well
        }

        var tryParseMethod = PropertyType.GetMethod("TryParse",
            Reflection.BindingFlags.Static | Reflection.BindingFlags.Public, null,
            new Type[] {typeof(string), PropertyType.MakeByRefType()}, null);

        //This is where I get lost


        return base.IsValid(value, validationContext);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        throw new NotImplementedException();
    }
}
public类NotAttribute:ValidationAttribute,IClientValidatable
{
公共类型属性类型{get;set;}
公共字符串NotEqualTo{get;private set;}
公共bool IgnoreWhitespace{get;set;}
公共布尔不区分大小写{get;set;}
公证人属性(字符串notEqualTo)
{
NotEqualTo=NotEqualTo;
}
受保护的重写ValidationResult有效(对象值,ValidationContext ValidationContext)
{
如果(PropertyType==null)PropertyType=typeof(字符串);
if(PropertyType==typeof(string))
{
//这是一个简单的例子,我们可以比较简单
var leftSide=value.toString空();
var rightSide=NotEqualTo??string.Empty;
if(忽略空格)
{
leftSide=leftSide.Trim();
rightSide=rightSide.Trim();
}
if(不区分大小写)
{
leftSide=leftSide.toupper不变量();
rightSide=rightSide.toupper不变量();
}
如果(leftSide!=rightSide)返回null;//一切正常
}
var tryParseMethod=PropertyType.GetMethod(“TryParse”,
Reflection.BindingFlags.Static | Reflection.BindingFlags.Public,null,
新类型[]{typeof(string),PropertyType.MakeByRefType()},null);
//这就是我迷路的地方
返回base.IsValid(值,validationContext);
}
公共IEnumerable GetClientValidationRules(ModelMetadata元数据、ControllerContext上下文)
{
抛出新的NotImplementedException();
}
}
我很确定我的
tryParseMethod
将返回一个对我理论上可以调用的对象方法的引用,但这里是我遇到问题的地方

我将如何调用它,传入在运行时确定的类型?这似乎是对泛型实现的强烈要求,但我不知道我可以在哪里注入它。此外,一旦我有了需要与“not”值进行比较的值,我就需要在运行时以某种方式强制转换它,这也需要泛型


我怎样才能做到这一点?我这样做完全是错误的吗?

这是一个静态方法,因此您应该能够调用它,而不需要调用类型为
PropertyType
的类的实例(请参阅)。因此,您可以在
tryParseMethod
上调用
Invoke

但是,
TryParse
方法本身需要一个类型为
PropertyType
的类的实例,因为它是
out
参数,所以需要使用
System.Activator.CreateInstance()

所以,大概是这样的

var parsedObject = System.Activator.CreateInstance(PropertyType);
bool parseSuceeded = tryParseMethod.Invoke(null, new [] { value, parsedObject });

你会做这项工作。

为什么你要用这些数据注释让你的生活变得复杂?只需看一看,其中有一个与ASP.NET MVC。您将看到验证从未如此简单。这似乎不支持自定义的不引人注目的客户端验证,或者我对页面的浏览不够深入?它与标准数据注释属性一样支持不引人注目的客户端验证。如果使用自定义验证逻辑,则需要实现相应的javascript。就我个人而言,我从不为此烦恼。我直接为表单编写jQuery.validate规则,而不使用Microsoft unobtrusive库。太复杂了。