5
public class StepClause
{
    public NamedStepClause Action1() {}

    public NamedStepClause Action2() {}
}

public class NamedStepClause : StepClause
{
    public StepClause Step(string name) {}
}

基本上,我希望能够做这样的事情:

var workflow = new Workflow().Configure()
    .Action1()
    .Step("abc").Action2()
    .Action2()
    .Step("def").Action1();

因此,有些“步骤”被命名,有些则没有。

我不喜欢的是 StepClause 知道它的派生类 NamedStepClause。

我尝试了几件事来让我觉得更好。我试图将事情转移到接口,但问题只是从具体转移到接口 - INamedStepClause 仍然需要从 IStepClause 派生,并且 IStepClause 需要返回 INamedStepClause 才能调用 Step()。我也可以让 Step() 成为一个完全独立的类型的一部分。那么我们就没有这个问题了,我们会有:

var workflow = new Workflow().Configure()
    .Step().Action1()
    .Step("abc").Action2()
    .Step().Action2()
    .Step("def").Action1();

没关系,但如果可能的话,我想将步骤命名设为可选。

我在这里找到了关于 SO 的另一篇文章,看起来很有趣且很有希望。你有什么意见?我认为最初的解决方案是完全不可接受的,或者是吗?

顺便说一句,这些操作方法将采用谓词和仿函数,我认为我不想采用额外的参数来命名那里的步骤。

对我来说,这一切的重点是只在一个地方和一个地方定义这些操作方法。因此,使用泛型和扩展方法的引用链接中的解决方案似乎是迄今为止最好的方法。

4

1 回答 1

8

我给你两个选择。

选项 A

var a = new A.NamedStepClause();

a.Action1()
    .Step("abc").Action2()
    .Action2()
    .Step("def").Action1();


namespace A
{
    public class StepClause<SC> where SC : StepClause<SC>
    {
        public SC Action1() { return null; }
        public SC Action2() { return null; }
    }

    public class NamedStepClause : StepClause<NamedStepClause>
    {
        public NamedStepClause Step(string name) { return null; }
    }
}

选项 B

var b = new B.StepClause();

b.Action1()
    .Step("abc").Action2()
    .Action2()
    .Step("def").Action1();

namespace B
{
    public class StepClause
    {
        public StepClause Action1() { return null; }
        public StepClause Action2() { return null; }
    }

    public static class StepClauseExtensions
    {
        public static StepClause Step(this StepClause @this, string name)
        { return null; }
    }
}

这两个选项都会编译并为您提供您正在寻找的流畅界面。我更倾向于使用选项 A,因为它可以让您访问课程的内部工作。使用扩展方法意味着您可能需要为您的类提供某种外部访问,从而破坏封装。

祝你好运!

于 2010-03-17T04:29:50.437 回答