Roo*_*ian 7 c# fluent-interface
我该怎么做才能说InvokeMethod可以调用一个方法,当使用像Repeat这样的特殊选项时,它应该在Repeat之后执行.
我现在的问题是该方法在知道必须被调用100次之前就已经执行了.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
有很多方法可以给这只猫剥皮,但我认为这种困难的一个根源在于您实际上在方法中调用了该方法InvokeMethod()(想想看!)。
通常,我们使用流畅的 API 将从内到外评估的语法转换为可以以从左到右的方式表达的语法。因此,接口的表达式构建器组件用于在整个表达式中构建状态,并且只有在最后才会发生“真正的工作”。
解决当前问题的一种解决方案是将每个操作及其关联选项(调用条件、重复计数等)排队,并添加一些ExecuteAll()方法以MethodExecuter在成员链末尾出队并执行完全配置的操作。
另一种解决方案是将所有执行选项放在InvokeMethod()方法内;就像是:
.Invoke(x => x.Method(A.Process).Repeat(100))
Run Code Online (Sandbox Code Playgroud)
这个方法看起来像:
public MethodExecuter Invoke(Action<IExecutionBuilder> executionBuilder)
{
var builder = new ExecutionBuilder();
executionBuilder(builder);
var action = builder.Action;
var repeat = builder.RepeatCount;
if (_condition)
{
for (int i = 1; i <= repeat; i++)
{
action();
}
}
return this;
}
Run Code Online (Sandbox Code Playgroud)
我还没有在 Visual Studio 中完成此操作,但其他项目类似于:
public interface IExecutionBuilder
{
IExecutionBuilder Method(Action action);
IExecutionBuilder Repeat(int count);
}
public class ExecutionBuilder : IExecutionBuilder
{
public ExecutionBuilder()
{
RepeatCount = 1; // default to repeat once
Action = () => {}; // default to do nothing, but not null
}
public IExecutionBuilder Method(Action action)
{
Action = action;
return this;
}
public IExecutionBuilder Repeat(int repeat)
{
RepeatCount = repeat;
return this;
}
public int RepeatCount { get; private set; }
public Action Action { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
请注意,RepeatCount和Action没有暴露在界面上。这样,您在调用时将看不到这些成员,但在方法内.Invoke(x => x.使用具体类时可以访问它们。ExecutionBuilderInvoke()