首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#构建用于方法调用的Fluent API

C#构建用于方法调用的Fluent API
EN

Stack Overflow用户
提问于 2011-06-07 16:29:59
回答 5查看 1.4K关注 0票数 7

我要做什么才能说InvokeMethod可以调用一个方法,并且当使用诸如Repeat之类的特殊选项时,它将在重复之后退出。

我现在的问题是,在它知道它必须被调用100次之前,这个方法就已经消失了。

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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;
    }
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-06-07 17:11:35

有很多方法可以剥去这只猫的皮,但我认为这一困难的一个原因在于,您实际上调用了InvokeMethod()方法中的方法(go图!)。

通常,我们使用fluent API将从内到外计算的语法转换为可以从左到右表达的语法。因此,接口的表达式生成器组件用于在整个表达式中构建状态,并且只有在最后才会发生“真正的工作”。

解决当前问题的一个解决方案是将每个操作与其相关的选项(调用条件、重复计数等)排队,并向ExecuteAll()添加一些MethodExecuter方法,以便在成员链的末尾排起队列并执行完全配置的操作。

另一种解决方案是将所有执行选项都放在InvokeMethod()方法中;如下所示:

代码语言:javascript
复制
.Invoke(x => x.Method(A.Process).Repeat(100))

此方法如下所示:

代码语言:javascript
复制
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中完成这一工作,但其他项如下所示:

代码语言:javascript
复制
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; }
 }

注意,RepeatCountAction没有在接口上公开。这样,您将不会在调用.Invoke(x => x.时看到这些成员,但是在使用Invoke()方法中的具体ExecutionBuilder类时,您可以访问它们。

票数 2
EN

Stack Overflow用户

发布于 2011-06-07 16:51:12

您所提供的看起来有点像编程工作流或状态机。为了在执行过程中捕获调用并尊重条件,您需要稍微改变您的方法。

不要在动作出现时调用它们,而是考虑将操作推入队列,然后提供运行状态机的机制。

代码语言:javascript
复制
new MethodInvoker()
       .ForAllInvocationsUseCondition(true)
           .InvokeMethod( Process.A ).Repeat(100)
       .Run();
票数 3
EN

Stack Overflow用户

发布于 2011-06-07 16:53:00

使用最后一种方法("go“或"execute")来启动实际操作。

代码语言:javascript
复制
      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();
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6268517

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档