我要做什么才能说InvokeMethod可以调用一个方法,并且当使用诸如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);
}
}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;
}
}发布于 2011-06-07 17:11:35
有很多方法可以剥去这只猫的皮,但我认为这一困难的一个原因在于,您实际上调用了InvokeMethod()方法中的方法(go图!)。
通常,我们使用fluent API将从内到外计算的语法转换为可以从左到右表达的语法。因此,接口的表达式生成器组件用于在整个表达式中构建状态,并且只有在最后才会发生“真正的工作”。
解决当前问题的一个解决方案是将每个操作与其相关的选项(调用条件、重复计数等)排队,并向ExecuteAll()添加一些MethodExecuter方法,以便在成员链的末尾排起队列并执行完全配置的操作。
另一种解决方案是将所有执行选项都放在InvokeMethod()方法中;如下所示:
.Invoke(x => x.Method(A.Process).Repeat(100))此方法如下所示:
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;
}我还没有在Visual中完成这一工作,但其他项如下所示:
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; }
}注意,RepeatCount和Action没有在接口上公开。这样,您将不会在调用.Invoke(x => x.时看到这些成员,但是在使用Invoke()方法中的具体ExecutionBuilder类时,您可以访问它们。
发布于 2011-06-07 16:51:12
您所提供的看起来有点像编程工作流或状态机。为了在执行过程中捕获调用并尊重条件,您需要稍微改变您的方法。
不要在动作出现时调用它们,而是考虑将操作推入队列,然后提供运行状态机的机制。
new MethodInvoker()
.ForAllInvocationsUseCondition(true)
.InvokeMethod( Process.A ).Repeat(100)
.Run();发布于 2011-06-07 16:53:00
使用最后一种方法("go“或"execute")来启动实际操作。
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)
.Go();https://stackoverflow.com/questions/6268517
复制相似问题