Лучший способ решить, какой подкласс нужен - PullRequest
2 голосов
/ 10 июня 2009

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

Все эти классы являются подклассами из одного класса, CheckoutContext, и тип используемого класса отмечается через перечисление.

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

<pre>CheckoutContext chooseSubclass(CheckoutCase c) { CheckoutContext output; switch (c): { case CheckoutCase.SingleItemNew: output = new SingleItemNew; break; case . . . return output; } }

Ответы [ 5 ]

4 голосов
/ 10 июня 2009

То, что вы реализуете - это Factory Pattern . Это стандартная практика, хотя обычно это означает написание большого количества повторяющегося кода (во многом аналогично вашему выражению switch, которое часто так и реализуется). Вы можете делать всякие причудливые вещи, такие как динамическое создание экземпляров посредством отражения, но не играйте с огнем. Просто придерживайтесь инструкции switch, и все будет в порядке.

1 голос
/ 10 июня 2009

Если существует большое количество случаев, я бы создал Dictionary<CheckoutCase, Type> и заполнил бы его один раз набором всех значений CheckoutCase и соответствующих типов CheckoutContext. Тогда вы могли бы использовать Activator.CreateInstance для возврата соответствующего типа вместо гигантского оператора switch.

0 голосов
/ 10 июня 2009

Вы можете создать атрибут, имеющий одно свойство, которое будет иметь тип CheckoutContext:

public class CheckoutContextAttribute : Attribute
{
   public Type CheckoutType{get;set;}
}

Затем в вашем перечислении вы можете указать правильный атрибут для правильного типа перечисления:

public enum CheckoutCase
{
   [CheckoutContext(CheckoutType=typeof(SingleItemNew)]
   SingleItemNew,
   ...
   ...
}

Затем в этом методе, где вам нужно отправить обратно правильный тип контекста, вы используете отражение и делаете что-то вроде этого:

public CheckoutContext GetContext(CheckoutCase c)
{
   FieldInfo field = c.GetType().GetField(c.ToString());
   object[] attribs = field.GetCustomAttributes(typeof(CheckoutContextAttribute),false);
   CheckountContext result = null;
   if(attribs.Length > 0)
   {
      CheckoutContextAttribute attrib = attribs[0] as CheckoutContextAttribute;
      Type type = attrib.CheckoutType;
      result = Activator.CreateInstance(type) as CheckountContext;
   }

   return result;
}

Это должно сработать. Просто добавьте проверку нуля / ошибок, чтобы быть в безопасности.

0 голосов
/ 10 июня 2009

Это называется шаблоном фабричного дизайна. Я хотел бы создать статический метод, который возвращает необходимый класс. Хорошей практикой здесь является реализация интерфейса и возврат интерфейса.

interface ICheckoutItem
{
    void CheckOut();
}

Пусть ваши предметы реализуют интерфейс. Затем в вашем заводском методе верните интерфейс каждого элемента.

ICheckoutItem chooseSubclass(CheckoutCase c)
{
ICheckoutItem output;
    switch (c):
    {
       case CheckoutCase.SingleItemNew:
         output = new SingleItemNew;
         break;
       case . . . 
  return output;
    }
}
0 голосов
/ 10 июня 2009

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

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

...