5

我最近发现了Presenter First并阅读了他们的白皮书和博客等。

在我发现的大多数示例中,事件并没有直接在接口上声明,而是作为它的一种方法。例如,

public interface IPuzzleView
{
    void SubscribeMoveRequest(PointDelegate listener);
    // vs
    event PointDelegate MoveRequest;
}

我不明白为什么。我以为我在某处看到了一篇论文/文章/博客,解释了这背后的原因,但我再也找不到了。所述文本还包含单元测试代码片段——我知道这一点是因为我记得对自己说,其中一个单元测试是不正确的。

更新:

下面是一个比较的例子:

public class Collect
{
    public static CollectAction<T> Argument<T>(int index,
        CollectAction<T>.Collect collectDelegate)
    {
        CollectAction<T> collect = new CollectAction<T>(index, collectDelegate);
        return collect;
    }
}

public interface IApplicationView
{
    event EventHandler Load;

    // or

    void SubscribeLoad(Action action);
}

Mockery mockery = new Mockery();
IApplicationView view = mockery.NewMock<IApplicationView>();
IApplicationModel model = mockery.NewMock<IApplicationModel>();

订阅方式:

Action savedAction = null;
Expect.Once.On(view).Method("SubscribeLoad").Will(
    Collect.Argument<Action>(0,
    delegate(Action action) { savedAction = action; }));
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
savedAction();
mockery.VerifyAllExpectationsHaveBeenMet();

与事件:

Expect.Once.On(view).EventAdd("Load", Is.Anything);
Expect.Once.On(model).Method("LoadModules");
new ApplicationPresenter(view, model);
Fire.Event("Load").On(view);
mockery.VerifyAllExpectationsHaveBeenMet();

仅供参考,上面的事件样式将无法正常工作,因为 ApplicationPresenter 会立即被垃圾收集并且连线永远不会发生。

4

1 回答 1

4

The short answer is: Presenter First evolved originally in the days of .NET 1.1 and VS2003, and C# events could be problematic.

Then-current testing/mocking tools didn't support our need to encapsulate event subscription and dispatch. Over time we came to feel that exposing the specific nature of events outside their emitting classes was burdening the client code with too much knowledge of the implementation, which made refactoring difficult.

For published examples, we wanted to avoid associating the Presenter First technique with a language-specific feature. (Eg, Java has no equivalent to C# events or delegates, but that doesn't mean you can't use the Observer pattern.)

I see that events, anonymous delegates and mocking tools have come a long way in the past few years. The next time I pick up a C# project, I will re-evaluate all of my assumptions on "the best way" to handle event subscription and dispatch. The above examples are intriguing.

To summarize our original, perhaps dated, reasons for hiding our use of C# events: - Mocking event subscription wasn't possible in unit tests - Occasionally we'd use a different internal mechanism to handle event subscription/dispatch. This led to inconsistency from one interface to another. - Several times we considered abandoning C# events even internally, as they behaved differently when no subscribers existed. Exposing events externally would have made it much harder to re-implement.

When Jiho Han messaged me with this question, he also inquired about data binding and a more fleshed-out PF example, which I have responded to by publishing a newer, fuller example of Presenter First and elaborating on Adapters.

于 2010-01-08T03:36:39.823 回答