Маршрутизация объекта в C # без использования операторов switch

Я пишу часть программного обеспечения на C # .net 4.0 и наткнулся на стену, чтобы убедиться, что кодовая база является расширяемой, многократно используемой и гибкой в ​​определенной области.

В него поступают данные, которые необходимо разбить на отдельные организационные единицы. Эти единицы необходимо будет изменять, сортировать, удалять и добавлять по мере роста компании.

Независимо от того, как мы разрезаем структуру данных, мы продолжаем сталкиваться с потоком условных операторов (более 100 или около того для начала), которых мы пытаемся избежать, что позволяет нам легко изменять OU.

Мы надеемся найти объектно-ориентированный метод, который позволил бы нам направлять объект в разные рабочие процессы на основе свойств этого объекта без необходимости каждый раз добавлять операторы переключения.

Так, например, предположим, что у меня есть объект под названием «Заказ», входящий в систему. Внутри этого объекта есть orderItems. Каждый из этих различных видов 'orderItems' должен запускать разные функции в коде для соответствующей обработки. У каждого «orderItem» свой рабочий процесс. Условное выражение в основном выглядит так -

if(order.orderitem == 'photo')
  {do this} 
else if(order.orderitem == 'canvas')
  {do this}

изменить: Попытка уточнить.


person Cory    schedule 17.06.2014    source источник
comment
Похоже, вам нужно применить шаблоны проектирования. Шаблоны Factory и Abstract Factory являются кандидатами, когда вам нужно переключать логику в зависимости от условий. В противном случае покажите нам код, чтобы мы могли предложить его соответственно реорганизовать.   -  person Kiran Hegde    schedule 17.06.2014
comment
Вы изучали инверсию управления (IoC)? http://stackoverflow.com/questions/250451/inversion-of-control-with-net   -  person Chris L    schedule 17.06.2014


Ответы (4)


Я не уверен, что ваш вопрос очень хорошо определен, вам нужно здесь гораздо больше конкретики - образец данных, образец кода, что вы пробовали ...

Независимо от того, как мы нарезаем структуру данных, мы продолжаем сталкиваться с потоком условных операторов (более 100 или около того для начала), которых мы пытаемся избежать.

Обычно это означает, что вы пытаетесь закодировать данные в своем коде - просто добавьте поле данных (или несколько).

Скорее всего, ваши if связаны друг с другом, сложно придумать 100 независимых if - это будет означать, что у вас есть 100 независимых ветвей для 100 независимых условий данных. Я в своей карьере не встречал ничего подобного, что действительно потребовало бы жесткого программирования 100 if.

В худшем случае вы можете создать дополнительное поле данных, содержащее файл конфигурации или даже сценарий по вашему выбору. В любом случае - ваши данные неполные, если вам нужно 100 ifs


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

public class OrderHandler{ 
  public static Dictionary<string,OrderHandler> Handlers = new Dictionary<string,OrderHandler>(){
  {"photo", new PhotoHandler()},
  {"canvas", new CanvasHandler()},
};

  public virtual void Handle(Order order){
    var handler = handlers[order.OrderType];
    handler.Handle(order);
  } 
}

public class PhotoHandler: OrderHandler{...}
public class CanvasHandler: OrderHandler{...}
person Sten Petrov    schedule 17.06.2014
comment
Я стараюсь быть максимально ясным. Так, например, предположим, что у меня есть объект под названием Order, входящий в систему. Внутри этого объекта есть orderItems. Каждый из этих различных видов 'orderItems' должен запускать разные функции в коде для соответствующей обработки. У каждого «orderItem» свой рабочий процесс. Условие выглядит примерно так - if (order.orderitem == 'photo') {do this} else if (order.orderitem == 'canvas') {do this} - person Cory; 17.06.2014
comment
@Cory вот простой пример решения - person Sten Petrov; 18.06.2014

То, что вы можете сделать, называется - «Маршрутизация на основе сообщений» или «Маршрутизация на основе содержимого сообщений» - в зависимости от того, как вы это реализуете.

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

Например: Предположим, в вашей организации есть следующие отделы - «Продукция растений», «Бумажные продукты», «Коммунальные услуги». Скажем, есть только одно место, куда приходят заказы - Заказ (модуль).
вот образец входящего сообщения.

Party:"ABC Cop"
Department: "Plant Product"
Qty: 50
Product: "Some plan"

Опубликуйте сообщение с этой информацией. В модуле, который обрабатывает заказы на «Продукты завода», настройте его так, чтобы он прослушивал сообщение с «Отделом = Продукты завода». Таким образом, вы возьмете ответственность на модули отделов, а не на основной модуль заказов.

Вы можете сделать это с помощью NServiceBus, BizTalk или любой другой ESB, которая у вас уже есть.

Вот как вы делаете это в BizTalk и это то, как вы можете сделать в NServiceBus

person Bitmask    schedule 17.06.2014

Рассматривали ли вы подтип OrderItem?

public class PhotoOrderItem : OrderItem {}
public class CanvasOrderItem : OrderItem {}

Другой вариант - использовать паттерн Стратегия. Добавьте дополнительное свойство в определение класса OrderItem для OrderProcessStrategy и используйте _5 _ / _ 6_, чтобы содержать всю другую логику.

public class OrderItem{
   public IOrderItemStrategy Strategy;
}

public interface IOrderItemStrategy{
   public void Checkout();
   public Control CheckoutStub{get;}
   public bool PreCheckoutValidate();
}

public class PhotoOrderStrategy : IOrderItemStrategy{}
public class CanvasOrderStrategy : IOrderItemStrategy{}
person Eric Falsken    schedule 17.06.2014

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

Имейте набор объектов «Инициаторы», которые определяют: 1) обработчик, который может обрабатывать сообщения оценщика, 2) простой логический тип, который может быть установлен, чтобы указать, знают ли они, что делать с чем-то в сообщении, и 3) Действие или Метод процесса, который может выполнять или запускать рабочий процесс. Разработайте интерфейс, чтобы их абстрагировать.

Выпустите сообщения. Посетите каждого Инициатора, спросите его, может ли он обработать lineItem, если он может сказать ему об этом. Обработка запускается «инициаторами», и они могут вызывать другие рабочие процессы и т. Д.

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

В целом, не зная более подробной информации, размера проекта, рабочих процессов, вариантов использования и т. д., комментировать сложно.

person Andrew    schedule 17.06.2014