What do I have to do to say that InvokeMethod can invoke a method and when using special options like Repeat it shall exexute after the Repeat.
My problem for now is that the method will already exexute before it knows that it has to be called 100 times.
class Program
{
static void Main()
{
const bool shouldRun = true;
new MethodExecuter()
.ForAllInvocationsUseCondition(!Context.WannaShutDown)
.InvokeMethod(A.Process).Repeat(100)
.When(shouldRun).ThenInvokeMethod(B.Process).Repeat(10)
.ForAllInvocationsUseCondition(Context.WannaShutDown)
.When(shouldRun).ThenInvokeMethod(C.Process);
}
}
MethodExpression
public class MethodExpression
{
private bool _isTrue = true;
private readonly MethodExecuter _methodExecuter;
public MethodExpression(bool isTrue, MethodExecuter methodExecuter)
{
_isTrue = isTrue;
_methodExecuter = methodExecuter;
}
public MethodExecuter ThenInvokeMethod(Action action)
{
if (_isTrue)
{
action.Invoke();
_isTrue = false;
}
return _methodExecuter;
}
}
MethodExecuter
public class MethodExecuter
{
private bool _condition;
private int _repeat = 1;
public MethodExpression When(bool isTrue)
{
return new MethodExpression(isTrue && _condition, this);
}
public MethodExecuter InvokeMethod(Action action)
{
if (_condition)
{
for (int i = 1; i <= _repeat; i++)
{
action.Invoke();
}
}
return this;
}
public MethodExecuter ForAllInvocationsUseCondition(bool condition)
{
_condition = condition;
return this;
}
public MethodExecuter Repeat(int repeat)
{
_repeat = repeat;
return this;
}
}
There are a lot of ways to skin this cat, but I think one source of this difficulty is in the fact that you actually invoke the method within the
InvokeMethod()method (go figure!).Typically, we use fluent APIs to turn syntax that is evaluated from the inside-out into something that can be expressed in a left-to-right fashion. Thus, the expression builder components of the interface are used to build up state throughout the expression, and only at the end does the “real work” happen.
One solution to your immediate problem is to queue up each action with its associated options (invocation conditions, repeat count, etc.), and add some
ExecuteAll()method toMethodExecuterthat dequeues and executes the fully configured actions at the end of the member chain.Another solution would be to put all of the execution options inside the
InvokeMethod()method; something like:This method would look something like:
I haven’t worked through this in Visual Studio, but the other items would be something like:
Note that
RepeatCountandActionare not exposed on the interface. This way, you will not see these members when calling.Invoke(x => x., but will have access to them when using the concreteExecutionBuilderclass inside theInvoke()method.