代码之家  ›  专栏  ›  技术社区  ›  Ben McCormack

如何确保字符串属性具有特定长度?

  •  0
  • Ben McCormack  · 技术社区  · 16 年前

    我创建了一些类,这些类将用于向数据库中的存储过程提供数据。这个 varchar varchar(6) 在将所有字符串属性传递给存储过程之前,我要验证它们的长度。

    有没有一个简单的,声明性的方法来做到这一点?


    属性

    public class MyDataClass
    {
         [MaxStringLength = 50]
         public string CompanyName { get; set; }
    }
    

    属性中的验证

    public class MyDataClass
    {
         private string _CompanyName;
         public string CompanyName
         {
             get {return _CompanyName;}
             set
             {
                  if (value.Length > 50)
                      throw new InvalidOperationException();
                  _CompanyName = value;
             }
         }
    }
    

    5 回复  |  直到 16 年前
        1
  •  2
  •   kbrimington    16 年前

    我将把它作为一个不同的答案发布,因为它与代码契约有着显著的不同。

    可以使用一种方法进行声明性验证,即使用字典或哈希表作为属性存储,并共享一个实用方法来执行验证。

    例如:

    // Example attribute class for MaxStringLength
    public class MaxStringLengthAttribute : Attribute
    {
        public int MaxLength { get; set; }
        public MaxStringLengthAttribute(int length) { this.MaxLength = length; }
    }
    
    // Class using the dictionary store and shared validation routine.
    public class MyDataClass
    {
        private Hashtable properties = new Hashtable();
    
        public string CompanyName
        {
            get { return GetValue<string>("CompanyName"); }
    
            [MaxStringLength(50)]
            set { SetValue<string>("CompanyName", value); }
        }
    
        public TResult GetValue<TResult>(string key)
        {
            return (TResult)(properties[key] ?? default(TResult));
        }
    
        public void SetValue<TValue>(string key, TValue value)
        {
            // Example retrieving attribute:
            var attributes = new StackTrace()
                                 .GetFrame(1)
                                 .GetMethod()
                                 .GetCustomAttributes(typeof(MaxStringLengthAttribute), true);
            // With the attribute in hand, perform validation here...
    
            properties[key] = value;
        }
    }
    

    您可以通过将堆栈跟踪设置为 demonstrated here . 反映属性属性,运行验证,然后 瞧!

    (英寸ASP.NET) ,仅通过更新 GetValue SetValue

    另一个注意事项是,如果使用这种方法,可以考虑将验证逻辑重构为一个验证实用程序类,以便在所有类型之间共享使用。这将有助于防止数据类在应用程序中变得过于庞大 赋值

        2
  •  2
  •   James Curran    16 年前

    好吧,不管你怎么做,执行的都会像你的第二种方法。所以窍门是让你的第一个方法扮演你的第二个。

    首先,它需要 [MaxStringLength(50)] . 接下来,我们要做的就是为这个类的Type对象添加一些数据。你仍然需要一种方法来使用这些数据。

    一种方法是二进制重写器。编译之后(但在执行之前),重写器将读取程序集,查找该属性,找到该属性时,添加代码进行检查。零售产品 PostSharp

    或者,您可以在运行时触发它。比如:

    public class MyDataClass 
    { 
         private string _CompanyName;
    
         [MaxStringLength(50)] 
         public string CompanyName 
         { 
             get {return _CompanyName;} 
             set 
             { 
                 ProcessValidation()
                  _CompanyName = value; 
             } 
         } 
    }
    

    这仍然很难看,但是如果您有许多验证属性,那就更好了。

        3
  •  1
  •   VdesmedT    16 年前

    通过从系统属性类并用AttributeUsage属性标记类,以便在字段上设置属性。

    这比第二种方法提供了更多的灵活性。如果您决定让SP接收过长字符串的前N个字符,则不必修改所有代码,只需修改解释该属性的代码。

    框架中确实有一些验证属性,但我不会使用这些属性,因为您可能会暗示一些您不期望的行为,并且您将无法以任何方式修改它们(如果您希望类似于[MaxLength(50,true)]的内容来指定使用前5O个字符是可以的。

        4
  •  1
  •   Wix    16 年前

    听起来像是商业规则。所以我把它放在一个Company类中(因为它是CompanyName),并在那里进行验证。我不明白为什么它需要复制和粘贴,如果你有它封装。

    一个属性或第二个示例都可以。但是,该属性允许在具有字符串长度约束的其他类中重用。

        5
  •  0
  •   kbrimington    16 年前

    .NET 4 Code Contracts 在MSDN的文章中。它们提供了一种方便而优雅的编码和分析代码假设的方法。值得一看。