Какими способами я могу убедиться, что строковое свойство имеет определенную длину? - PullRequest
0 голосов
/ 02 сентября 2010

Я создал несколько классов, которые будут использоваться для предоставления данных для хранимых процедур в моей базе данных. Параметры 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 ]

2 голосов
/ 02 сентября 2010

Я опубликую это как другой ответ, потому что он характерно отличается от кодовых контрактов.

Один из подходов, который вы можете использовать для декларативной проверки, - это использование словаря или хеш-таблицы в качестве хранилища свойств,и поделитесь утилитарным методом для проверки.

Например:

// 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;
    }
}

Вы можете получить свойство вызова с помощью отражения, обработав трассировку стека, как продемонстрировано здесь .Отразите атрибуты свойств, запустите проверку и вуаля! Однострочные геттеры / установщики, которые разделяют общую процедуру проверки.

Кроме этого, этот шаблон также удобен, поскольку вы можете разработатькласс для использования альтернативных словарных хранилищ свойств, таких как ViewState или Session (в ASP.NET) , путем обновления только GetValue и SetValue.

Еще одно примечаниеЕсли вы используете этот подход, вы можете рассмотреть реорганизацию логики валидации в класс утилиты валидации для совместного использования всеми вашими типами.Это должно помочь предотвратить слишком большой объем вашего класса данных в методе SetValue.

2 голосов
/ 02 сентября 2010

Ну, как бы ты ни шел, то, что выполняется, будет похоже на твой второй метод. Таким образом, хитрость заключается в том, чтобы ваш первый метод действовал вторым.

Прежде всего, это должно быть [MaxStringLength(50)]. Далее все, что мы делаем, это добавляем некоторые данные в объект Type для этого класса. Вам все еще нужен способ использовать эти данные.

Одним из способов было бы двоичное переписывание. После компиляции (но перед выполнением) переписчик считывает сборку в поисках этого атрибута и, находя его, добавляет код проверки. Розничный продукт PostSharp был разработан именно для этого типа вещей.

Кроме того, вы можете запустить его во время выполнения. Что-то вроде:

public class MyDataClass 
{ 
     private string _CompanyName;

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

Это все еще довольно уродливо, но немного лучше, если у вас есть несколько атрибутов проверки.

1 голос
/ 02 сентября 2010

Первый метод с использованием атрибута звучит хорошо.

Реализуйте свой атрибут путем наследования от класса System.Attribute и пометьте свой класс атрибутом AttributeUsage, чтобы ваш атрибут был установлен в поле.

Затем, используя отражение, проверьте наличие и значение атрибута перед отправкой значения в SP.

Это дает вам гораздо больше гибкости, чем второй метод. Если завтра вы решите позволить вашему SP получить первые N символов слишком длинной строки, вам не придется изменять весь код, а только тот, который интерпретирует атрибут.

В фреймворке действительно есть какой-то атрибут валидации, но я бы не стал использовать его, потому что вы можете подразумевать поведение, которого вы не ожидаете, и потому что вы не сможете изменить его каким-либо образом (прост, если вы хотите что-то вроде [MaxLength (50, true)], чтобы указать, что использование первых 5O символов в порядке.

1 голос
/ 02 сентября 2010

Звучит как бизнес-правило. Поэтому я бы поместил его в класс Company (поскольку это CompanyName) и провел там проверку. Я не понимаю, почему это потребовало бы копирования и вставки, если у вас есть это инкапсулированное.

Либо атрибут, либо ваш второй пример должны подойти. Однако атрибут допускает повторное использование в других классах с ограничениями длины строки.

0 голосов
/ 02 сентября 2010

Хотя это не совсем то же самое, недавно я узнал о .NET 4 кодовых контрактах в статье MSDN. Они обеспечивают удобный и элегантный способ кодирования и анализа предположений кода. На это стоит взглянуть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...