Q:

Design pattern for enum combination (method parameters)

I have a block of code similar to this one:
public bool DoMyThings(EnumRootAction root, EnumChildAction child){
          switch(root){
               case EnumRootAction.Type1:
                                switch(child){
                                       case EnumChildAction.Ac1: 
                                                    // DO something
                                                    break;
                                        case EnumChildAction.Ac2: 
                                                    // DO something
                                                    break;
                                        default: // child is not child of type root
                                                return false;
                                }
                                break;
                case EnumRootAction.Type2:
                                switch(child){
                                       case EnumChildAction.Ac1: 
                                                    // DO something
                                                    break;
                                        case EnumChildAction.Ac3: 
                                                    // DO something
                                                    break;
                                        default: // child is not child of type root
                                                return false;
                                }
                                break;
                ... // etc...
                default: 
                    return false;                       
        }
        return true;
     }

However, I do believe that it is a bad looking piece of code... :) ... the "consumer" of this service does not know the correct combination of root/child that are valid and might pass a wrong one.  
I thought of "spiting" it into several methods, something like: DoMyThingsForRootType1(EnumChildActionForType1 child) but in a long term term this is not so easy to change in my case. I explain why: if the signature of my service changes continuously I need to update the service protocol of all my real time clients.... update source code and deploy it again.... and at the present day the client can simply make these changes manually by changing some app.settings values.
At this point I am providing a single sheet of paper with the correct combinations but this is crap as well in my eyes.
Perhaps I am just looking at this from one perspective and somehow I am not being able to expand my horizons... this is why I would like to ear some feedback from you guys/gals... 
Is there a better design pattern for this?
At least some kind of way to inform the service's client of the valid combinations....
Thanks. 

A:

If you can use interfaces or base classes instead of enums you can harness the power of object-orientation to determine how the combinations are to be evaluated. This allows you to group the root/child action functionality in an easy-to-understand and easy-to-maintain way. It is somewhat long-winded however: 
    public interface IChildAction
    {
    }

    public class ChildAction1 : IChildAction
    {
    }

    public class ChildAction2 : IChildAction
    {
    }

    public class ChildAction3 : IChildAction
    {
    }

    public abstract class BaseRootAction
    {
        public virtual bool Process(ChildAction1 action)
        {
            return false;
        }

        public virtual bool Process(ChildAction2 action)
        {
            return false;
        }

        public virtual bool Process(ChildAction3 action)
        {
            return false;
        }
    }

    public class RootAction1 : BaseRootAction
    {
        public override bool Process(ChildAction1 action)
        {
            Console.WriteLine("Root action 1, Child action 1");
            return true;
        }

        public override bool Process(ChildAction2 action)
        {
            Console.WriteLine("Root action 1, Child action 2");
            return true;
        }
    }

    public class RootAction2 : BaseRootAction
    {
        public override bool Process(ChildAction1 action)
        {
            Console.WriteLine("Root action 2, Child action 1");
            return true;
        }

        public override bool Process(ChildAction3 action)
        {
            Console.WriteLine("Root action 2, Child action 3");
            return true;
        }
    }

    public class RootAction3 : BaseRootAction
    {
        public override bool Process(ChildAction2 action)
        {
            Console.WriteLine("Root action 3, Child action 2");
            return true;
        }
    }

    public bool DoMyThings(BaseRootAction rootAction, IChildAction childAction)
    {
        return rootAction.Process((dynamic)childAction);
    }

I also include my test method for completeness:
    private void Test()
    {
        List<BaseRootAction> rootActions = new List<BaseRootAction>() { new RootAction1(), new RootAction2(), new RootAction3()};
        List<IChildAction> childActions = new List<IChildAction>() { new ChildAction1(), new ChildAction2(), new ChildAction3()};
        foreach (BaseRootAction rootAction in rootActions)
        {
            foreach (IChildAction childAction in childActions)
            {
                bool result = DoMyThings(rootAction, childAction);
                Console.WriteLine(String.Format("Processed '{0}' / '{1}': Result = {2}", rootAction.GetType().Name, childAction.GetType().Name, result));
            }
        }
    }

If you need the Enums the action classes can be derived from them, but the solution becomes more bloated.

