我应该使用多个RegularExpression属性

时间:2016-02-26 13:06:22

标签: c#

更新8: 这个问题有一个新标题,希望它可以帮助其他人避免耗时的错误......

我有以下代码: (您需要对System.ComponentModel.DataAnnotations的引用)

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var itemModelX = new MyModel() { Name = "1<d" };

            var contextX = new ValidationContext(itemModelX, serviceProvider: null, items: null);
            var resultsX = new List<ValidationResult>();
            var isValidX = Validator.TryValidateObject(itemModelX, contextX, resultsX, true);

            if (isValidX)
                Console.WriteLine("Should not see this");

            Console.WriteLine("Finished");
            Console.ReadLine();
        }
    }

    public class MyModel
    {
        [MultipleRegExAttribute2(@"[^?.]{1,100}$")]
        [MultipleRegExAttribute2(@"^((?![><&])[\s\S])*$")]
        public string Name { get; set; }
    }

    [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)]
    public class MultipleRegExAttribute2 : RegularExpressionAttribute
    {
        public MultipleRegExAttribute2(string pattern) : base(pattern) { }
    }
}

在Visual Studio 2013 Premium Update 5中,输出为

  

“不应该看到这个”
  “完成”

在Visual Studio 2015 Enterprise Update 1中,输出为

  

“完成”

Roslyn是正确的,问题是2013年为什么不起作用? 我很确定这也是在2013年工作,不知道什么时候坏了,我没有以前的更新来测试它...
我正在使用.NET 4.5.1

更新1
即使我删除了对System.ComponentModel.DataAnnotations的引用并将代码添加到我的项目中(你可以找到代码here),我得到不同的输出。

更新2
忘了说只有当我有2个MultipleRegExAttributes时才会发生,如果我删除它按预期工作的第一个

更新3 我上传了整个解决方案here

更新4 我检查两个程序集生成的IL,但我看到的唯一区别是几个本地的初始化

VS2015

.locals init (
    [0] class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationContext contextX,
    [1] class [mscorlib]System.Collections.Generic.List`1<class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationResult> resultsX             )

VS2013

.locals init (
    [0] class ConsoleApp.MyModel itemModelX,
    [1] class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationContext contextX,
            [2] class [mscorlib]System.Collections.Generic.List`1<class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationResult> resultsX,
            [3] bool isValidX,
            [4] class ConsoleApp.MyModel '<>g__initLocal0'
        )

更新5
差不多......

  • VS2015只检查第二个属性(碰巧是我的那个) 在案件中关心)
  • VS2013只检查第一个参数......

更新6
经过许多个小时......   - 如果我有超过1个RegularExpressionAttribute
,似乎总会出现问题     这可能是我的错,因为我扩展了类并“覆盖”AllowMultiple

2.当我用VS2015编译时,为什么会得到不同的结果?
   返回属性的类是方法GetAttributes中的System.ComponentModel.TypeDescriptor     我必须看看那里有什么变化......

更新7
看来PropertyDescriptor / MemberDescriptor返回属性的方式发生了变化 在VS2015中它打印第二个正则表达式,在VS2013中打印第一个正则表达式 那么,以下哪一项是正确的?

  • a)这是一个实现细节,我不应该依赖这个
  • b)这是一个错误,因为它是一个突破性的变化
  • c)a和b
  • d)其他

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {

            var property = TypeDescriptor.GetProperties(typeof(MyModel))[0];
            var attribute = property.Attributes.Cast<Attribute>();
            foreach (var item in attribute)
                if (item is MultipleRegExAttribute2)
                    Console.WriteLine(((MultipleRegExAttribute2)item).GetPattern());
            Console.ReadLine();
        }
    }

    public class MyModel
    {
        [MultipleRegExAttribute2(@"[^?.]{1,100}$")]
        [MultipleRegExAttribute2(@"^((?![><&])[\s\S])*$")]
        public string Name { get; set; }
    }

    [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)]
    public class MultipleRegExAttribute2 : RegularExpressionAttribute
    {
        public MultipleRegExAttribute2(string pattern) : base(pattern) { }
        public string GetPattern() { return this.Pattern; }
    }
}

1 个答案:

答案 0 :(得分:1)

不要扩展RegularExpressionAttribute并将AllowMultiple设置为true 它会给你带来麻烦。
您可以创建从RegularExpressionAttribute继承的2个不同属性。

public class MyModel
{
    [MultipleRegExAttribute2(@"[^?.]{1,100}$")]
    [MultipleRegExAttribute3(@"^((?![><&])[\s\S])*$")]
    public string Name { get; set; }
}


public class MultipleRegExAttribute2 : RegularExpressionAttribute
{
    public MultipleRegExAttribute2(string pattern) : base(pattern) { }
}


public class MultipleRegExAttribute3 : RegularExpressionAttribute
{
    public MultipleRegExAttribute3(string pattern) : base(pattern) { }
}

更新

我的一位朋友向我展示了问题的根源 我必须覆盖TypeId属性 看到这个问题:Custom validation attribute with multiple instances problem
和这篇文章:The Importance of TypeId in ASP.NET MVC DataAnnotations Validation Attributes