2

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

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

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

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

4

5 回答 5

4

您正在实施的是工厂模式。这是一种标准做法,尽管它通常意味着编写大量重复的代码(很像您的 switch 语句,这通常是它们的实现方式)。你可以做各种花哨的事情,比如通过反射进行动态实例化,但不要玩火。只要坚持 switch 语句,你会没事的。

于 2009-06-10T15:27:15.237 回答
1

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

于 2009-06-10T15:35:40.383 回答
0

您可以使用自定义属性和工厂方法来实现这一点。让所有子类实现一个 CustomAttribute,比如 CheckOutCaseScenarioAttribute,它采用 CheckOutCase Enum 值。

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

于 2009-06-10T15:31:35.103 回答
0

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

interface ICheckoutItem
{
    void CheckOut();
}

让您的项目实现接口。然后在您的工厂方法中返回每个项目的接口。

ICheckoutItem chooseSubclass(CheckoutCase c)
{
ICheckoutItem output;
    switch (c):
    {
       case CheckoutCase.SingleItemNew:
         output = new SingleItemNew;
         break;
       case . . . 
  return output;
    }
}
于 2009-06-10T15:32:10.533 回答
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;
}

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

于 2009-06-10T15:51:47.967 回答