决定需要哪个子类的最佳方法

时间:2009-06-10 15:23:39

标签: c# enums subclassing

我正在为当前项目开发一个大型结帐应用程序。 这种结账有很多种情况,具体取决于用户的管理级别,他们如何进入结账,以及他们检查的项目类型,因此该过程通​​过一组上下文类从.aspx页面中抽象出来。

这些类都是来自单个类CheckoutContext的子类,并且要使用的类的类型通过枚举来记录。

是否有类似于typedef的东西我可以用来选择使用哪个子类,或者我应该只使用一个返回相关类的方法,如下所示:

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

5 个答案:

答案 0 :(得分:4)

您要实施的是Factory Pattern。这是一种标准做法,但它通常意味着编写大量重复代码(很像你的switch语句,通常是它们的实现方式)。你可以做各种奇特的事情,比如通过反射进行动态实例化,但不要玩火。只需坚持使用switch语句就可以了。

答案 1 :(得分:1)

如果有大量案例,我会创建一个Dictionary<CheckoutCase, Type>并使用所有CheckoutCase值和相应的CheckoutContext类型的集合填充一次。然后你可以使用Activator.CreateInstance来返回适当的类型而不是巨大的switch语句。

答案 2 :(得分:0)

您可以使用自定义属性和工厂方法实现此目的。让所有子类实现CustomAttribute,说CheckOutCaseScenarioAttribute获取CheckOutCase枚举值。

在工厂方法中,查找具有此枚举值设置的类型并创建对象。这样可以避免你的开关盒。如果您的工厂方法中没有任何其他初始化逻辑,这将起作用。

答案 3 :(得分:0)

这称为工厂设计模式。我将创建一个返回所需类的静态方法。这里的一个好习惯是实现一个接口并返回接口。

interface ICheckoutItem
{
    void CheckOut();
}

让您的物品实现界面。然后在您的工厂方法中返回每个项目的界面。

ICheckoutItem chooseSubclass(CheckoutCase c)
{
ICheckoutItem output;
    switch (c):
    {
       case CheckoutCase.SingleItemNew:
         output = new SingleItemNew;
         break;
       case . . . 
  return output;
    }
}

答案 4 :(得分:0)

您可以创建一个属性,该属性具有一个属于CheckoutContext类型的属性:

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

然后,在枚举上,您可以将正确的属性放在正确的枚举类型上:

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

然后,在那个你需要发送回正确的Context类型的方法中,你使用反射并做这样的事情:

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

这应该可以解决问题。只需添加一些空/错误检查即可。