Seit meinem Engagement für das frei MMORPG “The Mana World” ist es hier ein wenig stiller geworden. Dennoch habe ich heute einen kleinen Artikel bezüglich MVP in C#. Wie auch in meinem letzten Artikel über MVP in PHP, möchte ich nicht im Detail auf das Prinzip von MVP eingehen. Vielmehr geht es darum die Funktionsweise anhand eines einfachen Beispiels zu verstehen, anwenden zu können und MVP auch ohne komplexe Frameworks in eher kleinen Projekten anwenden zu können.
Um das MVP Prinzip zu demonstrieren genügen uns 4 einfache Klassen, bzw. Interfaces.
- Die View Klasse (eine einfache Form in C#)
- Der Presenter
- Das Interface zur Kommunikation zw. View und Presenter (implementiert von der View)
- Der BasePresenter (Basisklasse alle Presenter)
Mit den kurzen Erläuterungen starten wir in umgekehrter Reihenfolge.
Der BasePresenter
Der BasePresenter ist die Basisklasse aller Presenter und enthält eigentlich nur einen Verweis auf seine View. Um in den abgeleiteten Presentern sauber unsere Views ansprechen zu können, verwenden wir im BasePresenter Generics.
abstract class BasePresenter<T>
{
protected T _view;
public BasePresenter(T view)
{
this._view = view;
}
}
Das View Interface
Das View Interface enthält alle Methoden, die der Presenter benötigt um die View zu steuern. Beispielhaft sind hier drei einfache Methoden aufgeführt um Werte in der Form zu setzen, alle Werte zurückzusetzen, und um eine Fehlermeldung anzuzeigen. Die 4. Methode ShowStatus() nutzen wir nachher noch zur Demonstration von Delegates um Methoden einer View auch in “tieferen Regionen” des Programms anzusprechen. Diese Methode wird genutzt um einen Statustext und einen prozentualen Fortschritt einer Aktion darzustellen.
interface Ifrm_Main
{
void ShowErrorMessage(string message, params string[] pars);
void ClearDisplay();
void SetDisplay(object foobar);
void ShowStatus(string message, int pct);
}
Die View
Die View implementiert das View Interface und stellt somit alle Methoden für den Presenter zur Verfügung um die View von aussen zu steuern.
public class frm_Main : System.Windows.Forms.Form, Ifrm_Main
{
private frm_MainPresenter _presenter;
public frm_Main()
{
InitializeComponent();
this._presenter = new frm_MainPresenter(this);
}
}
Die View hat selbstverständlich auch einen Verweis auf ihren Presenter, denn sie muss ja schliesslich alle Benutzeraktionen und Events die auf der View geschehen, an ihn weiterleiten. Die verbindung zwischen View und Presenter wird im Konstruktor der View erzeugt. Somit kann eine neue View wie gewohnt instanziiert und geöffnet werden, auch mit MVP.
Der Presenter
Der Präsenter leitet, wie schon erwähnt, von der BasePresenter Klasse ab. Da diese Klasse Generics verwendet, müssen wir bei der Klassendefinition unseren Presenter und unsere View zusammenbringen.
class frm_MainPresenter : BasePresenter<Ifrm_Main>
{
public frm_MainPresenter(Ifrm_Main view)
: base(view)
{
// do initialization
}
}
Somit wäre eigentlich schon alles fertig und wir könnten mit dem Design unserer View anfangen. Wenn es da nicht noch immer ein kleines Problem gäbe bei dem ich schon die wildesten Lösungsansätze gesehen habe…
Wie kann ich während einer langen Verarbeitung, die nicht im Presenter sondern in diversen Helferklassen ausgeführt wird, Rückmeldungen an die View geben um den Status der Verarbeitung darzustellen?
In diesem Fall benötigen wir nun die 4. Methode “void ShowStatus(string message, int pct);”. Analog zu dieser Methode definieren wir einen Delegaten, der die gleiche Struktur wie unsere Methode besitzt:
delegate void ShowProgress(string message, int pct);
Unserer Bibliothek, welche die Verarbeitung vornimmt, erwartet nun beim Aufruf einen Verweis auf einen Delegaten.
public void doWork(string param1, int param2, ShowProgress callbackFunc);
Unser Presenter, der diese Funktion aufruft um die Verarbeitung anzustossen, gibt einfach eine Referenz auf die Methode der View mit.
doWork("Hello World", 42, this._view.ShowStatus);
In unserer Bibliothek können wir dann einfach, wann immer wir einen neuen Status auf unserer View setzen möchten einfach die Methode “callbackFunc” mit ihren zwei Parametern “message” und “pct” aufrufen.
Schlagworte: .NET, C#, Generics, MVP, The Mana World