Как создать список делегатов действий, когда необходимо различное количество и типы параметров - PullRequest
2 голосов
/ 11 ноября 2011

У нас есть набор из примерно двух десятков классов, которые наследуются от базового класса, который имеет абстрактный метод Validate. Конечно, у каждого класса есть разные потребности в проверке, но правила нужны в разных комбинациях между ними, так что, как вы можете себе представить, это привело к большому дублированию кода, например:

Класс А нуждается в правилах 1, 3, 6 и 9
Класс B нуждается в правилах 3, 4 и 8
Классу С нужны правила 1, 8 и 9
....

вы получите картинку.

Поэтому я подумал о том, чтобы выполнить простой рефакторинг и создать декоратор валидации, в котором каждое правило будет инкапсулировано в классе, и фабрику, которая создаст комбинацию валидации adhoc для каждого класса.

Затем я начал думать, что каждое правило настолько простое, что вместо создания всей верстки для декоратора, я мог бы просто хранить делегаты Action, хранящиеся на фабрике, которые бы заполняли List(Action(T)), чтобы каждый класс просто проходил через это список, выполняющий каждого делегата.

Проблема заключается в том, что количество и / или типы параметров варьируются в зависимости от каждого правила, например:

Правило 1 нуждается в обнуляемом DateTime, DateTime и перечислении.
Правило 2 нуждается в обнуляемом DateTime и DateTime.
Правило 3 нуждается в строке .....

Это что-то, что может быть выполнено, или у меня нет выбора, кроме как кодировать Декоратор?

Спасибо за ваши мысли и идеи.

UPDATE: Некоторые примеры правил:

if(EndTime.HasValue && StartTime > EndTime)  
     Throw new Exception (...);

if(Status == StatusEnum.Pass && !EndTime.HasValue)  
     Throw new Exception (...);

if(string.IsNullOrEmpty(ProcessName))
     Throw new Exception (...);

if(string.IsNullOrEmpty(ProductName))
   Throw new Exception (...);

if(string.IsNullOrEmpty(CustomerName))
   Throw new Exception (...);

Все участвующие классы имеют свойства DateTime? EndTime, DateTime StartTime, StatusEnum Status и string ProcessName.

Ответы [ 2 ]

1 голос
/ 11 ноября 2011

Во-первых, вы можете создать класс, содержащий все параметры с логическими значениями, указывающими, какие из них актуальны.Вы также можете сделать делегат Params, но это немного уродливее (также потребуется преобразовать ваши параметры в массив объектов).

лично, я бы пошел с классом, описывающим все параметры.

РЕДАКТИРОВАТЬ:

Вот пример идеи ValiationRuleParameters (класс, содержащий параметры):

    public class ValidationRulesParam
{
    private readonly Dictionary<string, object> _parameters = new Dictionary<string, object>();

    public bool AddParam(string name, object value)
    {
        if (!_parameters.ContainsKey(name))
            return false;
        _parameters.Add(name, value);
        return true;
    }

    public bool IsTypedParameterSet(string name, Type valueType)
    {
        object value;
        if (_parameters.TryGetValue(name, out value) == false)
            return false;
        return (value.GetType() == valueType);
    }

    public TValue GetParamValue<TValue>(string name)
    {
        object value;
        if (_parameters.TryGetValue(name, out value) == false)
            return default(TValue);
        if (!(value is TValue))
            return default(TValue);

        return (TValue)value;
    }

    public object this[string name]
    {
        get { return GetParamValue<object>(name); }
        set { AddParam(name, value); }
    }
}

Это немного похоже на комбинацию использования объекта params [] и используя простой словарь

Вы можете отправлять экземпляры этого класса в каждое выполняемое вами правило валидации (действие), и катионы могут проверять наличие параметра (и его типа).и получите его значение.

Это всего лишь пример (и многое можно улучшить), но он должен дать хорошую картину, выражающую идею.

0 голосов
/ 11 ноября 2011

Почему бы не создать интерфейс, называемый чем-то вроде IValidationParameter Тогда у каждого правила проверки есть реализация IValidationParameter. Например

public class Rule1ValidationParameter : IValidationParameter
{
    public DateTime? FirstDate { get; set; }
    public DateTime SecondDate { get; set; }
    pulbic MyEnum MyEnum { get; set; }
}

Затем составьте свой список List<Action<IValidationParameter>>

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