Question

I am working on a large-scale checkout application for a current project. This checkout has many cases depending on the user's admin level, how they got to the checkout, and what type of item they are checking out, and so the process is abstracted away from the .aspx pages via a set of context classes.

These classes all subclass from a single class, CheckoutContext, and the type of class to be used is noted via an enum.

Is there something similar to typedef I can use to choose which subclass to use, or should I simply have a method that returns the relevant class, like so:

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

Was it helpful?

Solution

If there are a large number of cases, I would create a Dictionary<CheckoutCase, Type> and populate it one time with the set of all CheckoutCase values and corresponding CheckoutContext Types. Then you could use Activator.CreateInstance to return the appropriate type instead of a gigantic switch statement.

OTHER TIPS

What you're implementing is a Factory Pattern. This is a standard practice, though it typically means writing a lot of repetitive code (much like your switch statement, which is often how they're implemented). You could do all sorts of fancy things like dynamic instantiation via reflection, but don't play with fire. Just stick with switch statement and you'll be fine.

You could implement this with a custom attribute and a factory method. Make all you Sub Classes implement a CustomAttribute say CheckOutCaseScenarioAttribute that takes the CheckOutCase Enum value.

Within your factory method, look for types that have this Enum Value set and create the object. This will avoid your switch case. This will work if you dont have any other initialization logic within your factory method.

This is called a Factory Design Pattern. I would create a static method that returns the needed class. A good practice here is to implement an Interface and return the interface.

interface ICheckoutItem
{
    void CheckOut();
}

Have your items implement the interface. Then in your factory method return the interface of each item.

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

You can create an attribute that has one property which would be the type of CheckoutContext:

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

Then, on your enum, you can put the correct attribute on the correct enum type:

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

Then, in that method where you need to send back the correct Context type you use reflection and do something like this:

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

This should do the trick. Just add some null / error checking to be safe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top