Documente Academic
Documente Profesional
Documente Cultură
NET - CodeProject
Model View
+
Licence
CPOL
.NET2.0.NET3.0.NET3.5C#ASP.NETArchitectDevWinFormsDesignIntermediate,
Bookmarked 54 times
An article outlining an implementation of the Model View Presenter pattern in .NET, contrasting it with existing implementations of MVP, MVC, and using co-dependant interfaces to allow for abstract coordination.
4.09 (22 votes)
q
View - The display portal for the system. Shows the interaction and display surface of the application.
Arguably a variant of MVC (Model View Controller), where a controller acts as an external mediator, the MVP pattern is distinct in that it puts the model further out of reach of the display implementation. Let's, for arguments sake, call the 'Presenter' aspect of MVP a Controller, and compare and contrast the roles of each entity in the different paradigms: Element Visually Model-View-Controller Model-View-Presenter
Model Application domain logic View Receives model elements from controller. Displays and interacts with element. Controller Supervises view/model, performs actions in response to events/changes.
Application domain logic Receives data from presenter, notifies presenter of interactions.
Delegates events to model. Re-maps model outgoing events into state changes.
Each technique has its own merits. Martin Fowler identifies MVP as a 'Passive View' variant of Model-View-Controller. In more traditional MVC, a view would receive an update and manipulate the model accordingly after being configured by its controller. In Passive View or MVP, a view notifies its presenter of the update and the presenter then makes the corresponding model changes on its behalf, acting as a bi-directional mapping layer.
This choice forces a few undesirable traits on us, but the key one is that you can't mock out the presenter or swap the implementation entirely. If the view needs to notify the presenter of changes, it needs to be coded against the specific
http://www.codeproject.com/KB/architecture/mvp_through_dotnet.aspx?display=Print (3 of 13)03-Aug-11 1:16:26 PM
view type. It's often argued that this approach is just fine when you're building things like web applications, since you rarely want to test your view implementation, and instead people tend to focus on testing presenters with mock views. Some developers aren't so comfortable with this though, and often there is need to mock out the presenter and allow the views to be built separately or even built mostly up-front (as will often be the case when working with design agencies).
The presenter works against the model, interacting with views via an interface. View implementations in turn receive updates and work against a presenter interface.
public interface IView<TViewContract, TPresenterContract> where TViewContract : IView<TViewContract, TPresenterContract> where TPresenterContract : IPresenter<TPresenterContract, TViewContract> { void AttachToPresenter(TPresenterContract presenter, bool requiresInitialState);
http://www.codeproject.com/KB/architecture/mvp_through_dotnet.aspx?display=Print (5 of 13)03-Aug-11 1:16:26 PM
void DetatchFromPresenter();
TPresenterContract Presenter { get; } } public interface IPresenter<TPresenterContract, TViewContract> where TPresenterContract : IPresenter&<TPresenterContract, TViewContract> where TViewContract : IView<TViewContract, TPresenterContract> { void ConnectView(TViewContract viewInstance, bool requiresState);
This seemingly odd generic syntax allows us to now have a bi-directional coupling between instances that are exclusively interface driven, giving us the ability to replace either end of the agreement and not sacrifice any strong typing! A presenter can maintain a strongly typed collection of views, but at the same time, the view can maintain a strongly typed presenter property and other facets. To use these interfaces, simply declare a contract pair of the form:
The corresponding classes that implement these interfaces will have strongly typed mechanisms to enable inter-object communication.
The relationship between the various libraries in the example project is as follows:
The application could use Unity or any other Inversion of Control mechanism to perform the activation and connection of the pieces of the puzzle. However, rather than turn this article into a tutorial on the Enterprise Library, I'll leave that one to the reader! In terms of specific implementation - the orchestrator element in the example application is a simple Windows form, the model and presenter are both conventional classes. The presenter inherits from a base presenter class that deals with many of the more tedium prone aspects of implementation (such as managing a collection of connected views, etc.). The view itself is implemented as a WinForms UserControl. and shown twice on the form, and looks like this:
When you change the time-zone of one view, the other also receives the update (through the coordination logic of the presenter, acting in response to model changes). The data exchange is possible because of the contract coupling.
And there you have it. A Model-View-Presenter pattern with bi-directional strong typing of communication, but also abstracted from concrete classes.
views with the same reliable pattern. If you wanted to change this pattern to enable 'Active View', rather than 'Passive View', the only change needed is to have the model interface passed through to it by the presenter. This would allow the view class to interact with the model directly, but still allow the events to bubble through to the presenter and cause the view to receive corresponding updates.
History
q
10 October 2009 - Initial draft (+ Update to fix formatting oddities that made the generics bit look odd).
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
Steve Gray is a Senior Developer at a British insurance company, working on a popular aggregator. When he's not writing ASP .NET, it's because there's SQL or WCF to write instead.