Search code examples
c#control-flow

Strange control flow


I'm working on a framework in C# that will depend on pluggable components implemented as classes inheriting a base class. In order to make the components as simple as possible, I am working on some weird control flow.

The base class includes a static method RunStep(parameter). This method is called a number of times by the inheriting class, and each time it is called a condition is checked. If this condition happens to be false, I want the calling method to stop and return. A simplified working version of the code would be:

Base class:

class MyBase
{
  private static object RunStep(string parameter)
  {
    if(SomeFunction(parameter))
       return SomeOtherFunction(parameter);
    else
       return null;
  }  
}

Inheriting class:

class MyInheritor
{
  public void Run()
  {
     object result = RunStep("mystring1");
     if(null != result)
     {
        //perform some logic on result
        result = RunStep("mystring2");
        if(null != result){
            //perform some different logic on result
            RunStep("mystring3");
        }
     }
  }
}

What I am wondering is whether it is possible to do something in the base class so that I can simplify the inheriting class to this:

class MyInheritor2
{
  public void Run()
  {
     object result = RunStep("mystring1");
     //perform some logic on result
     result = RunStep("mystring2");
     //perform some different logic on result
     result = RunStep("mystring3");
     }
  }
}

I would put the parameters in a list and loop over them, but there is logic that needs to happen after each call to the RunStep method, and the logic is different each time. This takes a loop off the table. Also note that the logic between the RunStep calls accesses properties on result, so it crashes without the null checks.

It may seem like a trivial thing, but there may be thousands of these Inheriting classes and simplifying them is a big deal.


Solution

  • Let the base class to control the execution flow:

    class Base
    {
        private readonly List<Tuple<string, Action>> steps = new List<Tuple<string, Action>>();
    
        protected void RegisterStep(string parameter, Action someLogic)
        {
            steps.Add(Tuple.Create(parameter, someLogic));
        }
    
        protected void Run()
        {
            foreach (var step in steps)
            {
                var result = RunStep(step.Item1);
    
                if (result == null)
                {
                    break;
                }
    
                // perform some logic
                step.Item2();
            }
        }
    
        private object RunStep(string parameter)
        {
            // some implementation
            return null;
        }
    }
    
    class Derived : Base
    {
        public Derived()
        {
            RegisterStep("1", () => { });
            RegisterStep("2", () => { });
            RegisterStep("3", () => { });
    
            // etc
        }
    }