-
ACHTUNG - NEUES BLOG
Ab sofort steht unter http://devtyr.norberteder.com mein neues Blog zur Verfügung. Dieses Blog wird nicht weiter betreut, bleibt aber erhalten. Neue Eintr%auml;ge erfolgen nur mehr im neuen Blog. Kommentare werden ebenfalls nicht mehr behandelt. Wer weiterhin meinen Einträgen und Aktivitäten folgen möchte, möge bitte RSS-Feeds, Verlinkungen etc. an die neue Location anpassen.
|
WPF, NHibernate, ObservableCollection und Patterns
10.08.08 - Entwicklung, Diskussionen, Patterns, .NET, WPF Beitrag von Norbert Eder| | Im Beitrag ObservableCollection und NHibernate hatte ich einen Link zu einem Artikel gepostet, der zeigt, wie man NHibernate dazu bringt, mit einer ObservableCollection zu arbeiten.
Nun, ein paar Tage später, finde ich die Sache dann doch nicht mehr ganz so toll, gerade wenn Patterns mit ins Spiel kommen (was hoffentlich der Fall ist). Man nehme als Beispiel die bereits von mir vorgestellten Patterns MVC für WPF und Model-View-ViewModel. Diese beiden Patterns unterscheiden sich unter anderem dadurch, dass beim MVC Controller und Model komplett getrennt sind. Beim MVVM ist dies zwar auch der Fall, jedoch stellt das ViewModel sowohl die Controller-Funktionalität zur Verfügung, als auch eine gewrappte Form des Models.
Was bedeutet dies nun konkret?
Bei der Verwendung des MVVM Patterns zusammen mit NHibernate bedarf es keiner speziellen Erweiterung oder Anpassung. Das Model verwendet weder eine ObservableCollection noch wird irgendein für WPF benötigtes Interface implementiert (siehe beispielsweise INotifyPropertyChanged). Damit ist es möglich, NHibernate zu nutzen, wie es auch ausgeliefert wird. Beim MVC-Pattern müsste hier der im verlinkten Artikel angesprochene Handkniff getätigt werden, um in den Genuss der für das Data Binding notwendigen Events zu gelangen.
Was kann daraus abgeleitet werden?
Der – zumindest für mich – wesentliche Punkt ist, dass es sinnvoll wäre, das zu verwenden, was sich bereits vielfach bewährt hat. NHibernate hat sich bereits in sehr vielen Projekten bewährt und man kann sich auf eine korrekte Funktionsweise verlassen. Aus diesem Grund würde ich eher die Finger von einer ObservableCollection-spezifischen Erweiterung lassen (auch wenn es lediglich eine Handvoll Klassen sind) und hier auf das MVVM-Pattern zu setzen, welches eben diese Änderung nicht benötigt.
Damit muss man sich bei einem Update keine Sorgen machen und wer weiß, vielleicht gibt es ja bald eine entsprechende Unterstützung.
Was meint ihr dazu?
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Gewinnspiel zum Technical Summit 2008
04.08.08 - Entwicklung, .NET, Internet, Community Beitrag von Norbert Eder| |
Das Microsoft Technical Summit findet immer dann statt, wenn es viel Neues für professionelle Entwickler, Architekten, Entwicklungsleiter, IT-Projektleiter und IT-Projektmanager zu berichten gibt - heuer von 20. - 21. November 2008 (Preconference am 19. November). Dieses Jahr sind die Highlights die Produkte und Services von morgen, die ganz aktuell auf der PDC 2008 bekannt gegeben und erstmalig auf dem Microsoft Technical Summit in Deutschland vorgestellt werden. Bis zum 19.09.2008 läuft noch der Early-Bird-Preis. Anmeldung und zusätzliche Infos unter: www.technical-summit.de
Im Zeitraum vom 06.08.2008 - 10.09.2008 gibt es nun die Möglichkeit, 2 kostenfreie Eintrittskarten für das Technical Summit, sowie 1 Visual Studio 2008 zu gewinnen. Hierfür sind die untenstehenden Fragen zu beantworten und die Lösungen innerhalb des genannten Zeitraumes per Email an me[at]norberteder[dot]com zu senden.
Gewinnfragen
1) Frage:
Wie lautet das Motto des 2008 Microsoft Technical Summit?
Antwortmöglichkeiten:
a) Developer, Developer, Developer!
b) Technologien von morgen, schon heute!
c) Microsoft, Microsoft, Microsoft!
d) Alles für Entwickler!
Lösungslink: http://go.microsoft.com/?linkid=9298435
2) Frage:
Wie heißt die aktuelle Visual Studio Version?
Antwortmöglichkeiten:
a) Visual Studio 2008
b) Visual Studio 2007
c) Visual Studio 2006
d) Visual Studio 2005
Lösungslink: http://go.microsoft.com/?linkid=9298436
3) Frage:
Bis wann läuft die Early-Bird-Promotion des Microsoft Technical Summits?
Antwortmöglichkeiten:
a) 19.09.2008
b) 10.09.2008
c) 19.10.2008
d) 24.12.2008
Lösungslink: http://go.microsoft.com/?linkid=9298437
4) Frage:
Wann wurden die ersten Vortragsthemen und Sprecher publiziert?
Antwortmöglichkeiten:
a) 19.05.2008
b) 11.06.2008
c) 23.06.2008
d) 07.07.2008
Lösungslink: http://go.microsoft.com/?linkid=9298438
Weitere Informationen über das Microsoft Technical Summit 2008 können über die offizielle Website unter http://www.technical-summit.de bezogen werden.
Wichtig: Noch bis zum 19.09.08 kann unter Verwendung des günstigen Early-Bird-Tarifs gebucht werden.
| | | 2 Kommentare
- 259 mal angesehen
| 2 Trackbacks
| Permalink | Trackback-URL |
WPF und MVC
08.06.08 - Entwicklung, Diskussionen, Patterns, .NET, WPF Beitrag von Norbert Eder| | Anwendungen sollten nicht nur schön anzusehen sein, sondern auch das robust und korrekt tun, wofür sie geschaffen wurden. Damit dem so ist, muss sich der Entwickler/Architekt natürlich zu Beginn eines Projektes so einige Gedanken machen. Denn nur durch ein gutes Grundgerüst werden Anforderungen á la Erweiterbarkeit, Testbarkeit, einfache Wartung usw. auch erfüllt.
Das Model View Controller Pattern ist da so ein Ansatz. Mittlerweile Jahrzehnte am Buckel hatte sich dieses Pattern immer wieder bewährt (in seiner ursprünglichen Form oder in einer abgewandelten).
Wie nun die Windows Presentation Foundation mit dem Model View Controller Pattern zusammen arbeitet, zeigt der Artikel MVC Pattern mit WPF verwenden, welchen ich gestern auf .NET GUI veröffentlicht habe.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Nervig hoch 2: FxCop + WPF
14.05.08 - Entwicklung, Qualitätsmgmt., .NET, WPF Beitrag von Norbert Eder| | Ein Großteil des FxCop Ruleset ist bei meinen Projekten ständig aktiviert und hilft so, den Code sauberer, sicherer und performanter zu halten.
Aber gerade in Kombination mit WPF ergeben sich daraus natürlich einige Probleme oder besser gesagt, Ärgernisse. Nehmen wir die Regel CA1823. Diese besagt, dass ein Feld nicht verwendet wird, oder ihm nie ein Wert zugewiesen wurde. Derartige Regeln werden bei mir grundsätzlich als Fehler und nicht als Warnung behandelt.
Wie kommt man nun dazu, sich über diesen Fehler zu ärgern? Ganz einfach. Man vergebe einem Element einen x:Name. Dadurch wird es im generierten File (.g.cs) angelegt, damit aus der Codebehind-Datei darauf zugegriffen werden kann. Eventuell möchte man dies jedoch nicht, sondern vergibt dem Element bloß einen Namen, um per Binding darauf zuzugreifen.
Und schon taucht dieser Fehler auf und schreit nahezu danach, suppressed zu werden - was ja eigentlich vermieden werden sollte.
Wäre schön, wenn sich diesbezüglich zukünftig etwas tun würde ..
| | | 8 Kommentare
- 15584 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL |
WPF ist so extrem kompliziert ...
30.04.08 - Entwicklung, Diskussionen, .NET, WPF Beitrag von Norbert Eder| | ... liest man so immer wieder in allen Foren, die sich auch nur annähernde mit der Thematik beschäftigen. Das ist auch durchaus korrekt - zumindest zu Beginn.
Dadurch, dass sich sehr viele Konzepte geändret haben und natürlich jede Menge neues hinzukam, hat sich die Entwicklung von grafischen Oberflächen drastisch geändert. Das resultiert natürlich darin, dass die Lernkurve eine viel steilere ist und zudem viel vorhandenes Wissen verworfen werden muss.
Aber bei Windows Forms konnte ich das immer so machen. Oder so ähnlich lesen sich Beiträge. Mein Rat: Vergesst, was ihr von Windows Forms kennt. Anders ist es kaum zu formulieren.
Windows Forms war gestern (ganz so drastisch ist es nicht, aber aus Sicht der Vision von WPF dann doch wieder). Es ist wichtig die neuen Konzepte zu erfassen und sie verstehen zu lernen. Erst dann sind erste erfolgreiche Schritte tatsächlich möglich.
Es ist nicht bloß die Trennung zwischen Präsentation und Logik, die WPF als neuartig erscheinen läßt. Nein, WPF verwendet teilweise auch Techniken, die schon zig Jahre alt sind. Eben eine Mischung aus GDI/GDI+, Web, Windows Forms usw. Das alles auf Basis von DirectX und noch dazu mit einem unterschiedlichen Rendering-Mechanismus.
Es haben sich nicht nur die Möglichkeiten verändert, nein. Auch Gedanken müssen anders gedacht werden. Andere Schritte als bisher führen zum Ziel. Vieles erscheint im ersten Moment als sehr kompliziert, zeigt aber erst nach einer gewissen Einarbeitungsphase den wahren Reiz und die wahren Möglichkeiten. Wer über die ersten Frust-Momente hinweg kommt, der hat es geschafft.
Daher all denjenigen, die sich selbst in Frage stellen, denen ich in diversen Foren Mut machen konnte oder diejenigen, die diesbezüglich eine Aussage von mir per Mail "eingefordert" haben: Versucht die Konzepte dahinter zu verstehen und befreit euch vom Gedanken, wie es denn unter Windows Forms funktionieren würde ...
| | | 3 Kommentare
- 1278 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL |
.NET BlogBook Ausgabe 6
14.04.08 - Entwicklung, Diskussionen, Patterns, Software Testing, Projektmgmt., Qualitätsmgmt., .NET, Grundlagen, Base Framework, WPF, ASP.NET, Silverlight, Mobile Devices, Datenverwaltung, Visual Studio, Allerlei, Microsoft Office, SQL Server Beitrag von Norbert Eder| | Ab sofort steht die 6. Ausgabe des .NET BlogBooks zur Verfügung. Insgesamt stehen nun fast 330 Seiten an puren Informationen und Praxiswissen zur Verfügung.
Noch dazu wurden einige Anregungen aufgegriffen. Es gibt ein neues Cover (ein herzliches Dankeschön an 69° media solutions). Ebenfalls wurden unnötige dunkle Stellen entfernt, die beim Ausdrucken maximal Toner verbrauchen, sonst jedoch keinerlei Wirkung erzielen.
Hauptsächlich wurde das BlogBook um Wissen rund um die Windows Presentation Foundation erweitert, aber auch andere Punkte kamen hinzu. Ein Blick lohnt sich allemal.
Weitere Informationen sind auf der Homepage unter http://www.dotnet-blogbook.com zu finden.
Für Anregungen, Wünsche und (konstruktive) Kritik haben wir natürlich weiterhin ein offenes Ohr.
| | | 6 Kommentare
- 1356 mal angesehen
| 1 Trackbacks
| Permalink | Trackback-URL |
Code Analysis und von WPF generierter Code
07.04.08 - Entwicklung, Diskussionen, .NET, Grundlagen, WPF Beitrag von Norbert Eder| | Die lokale Code Analyse durch Visual Studio 2008 ist eine sehr hilfreiche Sache, um oft gemachte Unschönheiten, eventuelle Performance- und/oder Security-Probleme früh zu erkennen oder auch nur, um die korrekte Namensgebung zu beachten.
Werden die Richtlinien aktiviert (unter den Projekteigenschaften) und zudem einige dieser Richtlinien auf Error gestellt (standardmäßig sind alle als Warnings eingetragen), dann ist man gezwungen, eben diese auch tatsächlich zu beheben. Kein schlechter Weg, um die Qualität des Codes früh auf einen entsprechenden Standard zu heben.
Allerdings gibt es dabei auch einen Haken:
Es gibt die Möglichkeit, generierten Code von der Überprüfung auszunehmen. Dies ist sehr sinnvoll, wenn Code von 3rd-Party-Tools generiert wird und es keine Möglichkeit gibt, die Generierung zu beeinflussen d.h. etwaige Warnings oder Errors los zu werden. Dies kann in den Projekt-Eigenschaften eingestellt werden:
Die WPF selbst generiert ja aus dem definierten XAML im Hintergrund den notwendigen Sourcecode. Wird ein neues Fenster angelegt, besteht dieses aus zwei Dateien:
- Window1.xaml
- Window1.xaml.cs
In der Window1.xaml kann nun per XAML Markup die einzelnen Elemente definiert werden. WIndow1.xaml.cs ist die Codebehind-Datei und enthält den notwendigen Sourcecode (Eventhandler etc.). Nun muss aus der XAML-Datei einiges an Code generiert werden:
- Deklaration der einzelnen Elemente, damit via Sourcecode darauf zugegriffen werden kann.
- Methode InitializComponent
- Methode Connect
All das landet in der Datei Window1.g.cs. Wird also im Hintergrund für uns generiert. (Daher das g in der Endung). Blöderweise erhält diese Datei kein GeneratedCodeAttribute, wodurch die Prüfung auf die Richtlinien hin unterdrückt werden würde.
Im zu Grunde liegenden MSDN-Beitrag findet sich auch kein Hinweis darauf, schließlich wird WPF dort auch noch gar nicht behandelt.
Der einzige Ausweg daraus ist, den erhaltenden Fehler per SuppressMessage auszuklammern und zwar global für den gesamten Namespace. Eine Ausklammerung direkt im Source würde keine dauerhafte Änderung bringen, da das SuppressMessage-Attribute bei der nächsten Generierung überschrieben werden würde.
Hier sollte wohl noch etwas gemacht werden ...
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
WPF vs WinForms: Softwareentwickler Performance-Test
31.03.08 - Entwicklung, Diskussionen, .NET, WPF Beitrag von Norbert Eder| | Was macht man Wochenends am Abend, wenn man mit einem anderen Softwareentwickler zusammen sitzt und über einiges aus der eigenen Branche sinniert? Ganz einfach, man kommt auf lustige Ideen und setzt diese dann auch gleich um (oder versucht es zumindest). So vergangenes Wochenende geschehen.
Ausgangspunkt war ein Thread auf dem .NET-Forum.de. Hier kam im Laufe einer Diskussion auf, dass es doch wesentlich schneller und einfacher unter WinForms möglich ist, eine Oberfläche zu erstellen. Schließlich muss man lediglich die einzelnen Elemente in den Designer ziehen, ein wenig konfigurieren und fertig ist die Lösung.
Dem konnte ich so nicht gänzlich zustimmen, zumal man (vorausgesetzt ist weniger ein gekonnter Umgang mit der Maus, vielmehr ist die Fingerfertigkeit bezüglich Tastatur gefragt) in der deklarativen Variante (XAML) sehr gut mittels Copy & Paste (Achtung, Murphy lauert) arbeiten kann und einem so sehr viel Tippslerei erspart bleibt.
Gut, also wurde ein Testszenario ersonnen: Eine kleine Anwendung, die mit Daten aus einem XML gefüttert wird, diese anzeigen soll und zusätzlich die Funktionalitäten Neu, Edit und Save behandeln sollte. Nachdem die Anforderungen definiert wurden musste noch die Stoppuhr gestartet werden und schon konnte es losgehen.
Leider hatten wir keine Videokamera zur Verfügung, sonst hätten wir es in der Tat gefilmt und online gestellt (auch wenn die Lösungen wirklich schmutzig waren), aber der zeitliche Unterschied war schon recht eklatant. Und damit meine ich, dass die WPF-Variante ungefähr 50% der Entwicklungszeit unter WinForms benötigte.
Nun. Natürlich ist dieser Test in keinster Weise wirklich aussagekräftig, noch ist er für den Leser nachvollziehbar (mit Video sähe es anders aus), aber es war grundsätzlich als kleiner Test gedacht um einen ungefähren Anhaltspunkt zu bekommen. Das was sich dabei halt herausgestellt hat war, dass die WPF Lösung auf jeden Fall schneller implementiert war und zusätzlich noch die Möglichkeit der Customization bot, d.h. das Aussehen konnte vollständig angepasst werden. Bei der WinForms-Anwendung: Niete.
Das spricht dann schon wieder eine deutlichere Sprache. Kürzere Implementierungszeit und höhere Anpassbarkeit. Schon eine nette Sache.
Interessant wäre nun der direkte Vergleich in einer größer angelegten Anwendung. D.h. mit einer Implementierungszeit von mehr als 5 MD. Wird sich in der Realität zwar vermutlich nicht spielen, aber durchaus ein interessantes Experiment. Denn gerade auf diesem Gebiet gibt es zahlreiche Spekulationen, wodurch natürlich viele Interessierte verunsichert werden und somit lieber die Finger von dieser Technologie lassen.
| | | 2 Kommentare
- 1252 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL |
Aber mit Windows Forms bin ich doch viel schneller …
14.03.08 - Entwicklung, Diskussionen, Grundlagen, WPF Beitrag von Norbert Eder| | Genau diese Aussage ist mir bei Diskussionen rund um die Windows Presentation Foundation immer wieder untergekommen. Gerade wenn es um kleine Anwendungen geht, wird immer noch hauptsächlich auf Windows Forms gesetzt. Hier kommen natürlich einige Punkte zu tragen, die ich schon an diversen Stellen aufgeführt habe:
- Gewohnheit: Windows Forms kennt man und weiß sie auch einzusetzen. Probleme sind genauso bekannt wie die möglichen Umsetzungsvarianten. Der Umstieg zu einer deklarativen Form (obwohl das ja auch nur ein Teil der WPF ist) ist somit nicht einfach zu bewerkstelligen, zumal bei kleinen Anwendungen, Tools, Hilfen die Vorteile bei weitem nicht so klar auf der Hand liegen.
- Es ist neu. Neues verursacht immer wieder Angst. Man weiß nicht, womit genau man’s zu tun hat, wie es reagiert, was man damit alles machen kann. Im ersten Schritt werden daher grundlegende Informationen besorgt, welche dann natürlich aber auch sehr schnell zeigen können, dass etwas eventuell aufwändiger ist, als man es bisher gewohnt war. In einigen Fällen (und hier zähle ich die WPF dazu) wirkt dies jedoch nur auf den ersten Blick so. Allerdings muss hier auch die Größe der Anwendung berücksichtigt werden.
- Es ist anders. Ganz klar, es ist natürlich anders, weil es neu ist. Bei neuen Techniken werden oft neue (oder aufgewärmte) Wege gegangen. Im Falle der WPF handelt es sich dabei um den Einsatz einer deklarativen Programmierung, soweit es zumindest XAML betrifft. Dies mag auf den ersten Blick etwas aufwändig erscheinen, dennoch ermöglicht gerade dies ungeahnte Möglichkeiten in der Trennung zwischen Design und Logik.
Zusätzlich zu diesen Punkten wird oftmals der im Visual Studio integrierte WPF Designer (Cider) kritisiert. Es wird bemängelt, dass Oberflächen nun nicht mehr so einfach und schnell erstellt werden können, wie dies unter Windows Forms der Fall ist. Das ist grundsätzlich schon richtig. Für diese Fälle gibt es Tools á la Expression Blend (dazu kommen wir noch). Auch unterscheidet sich hier ein bestimmter Punkt ganz gewaltig: Gestaltungsfreiheit.
War ich unter den Windows Forms noch an die angebotenen Gestaltungsmöglichkeiten des entsprechenden Steuerelements gebunden, ist dies unter WPF großteils so nicht mehr der Fall. Durch die Möglichkeit, beliebige Steuerelemente ineinander zu verschachteln, kann ich als Designer/Entwickler gänzlich neue Steuerelemente erzeugen, ohne wirklich programmieren zu müssen. Unter den Windows Forms musste ich für eine eigene Konstellation eben mal schnell ableiten und meinen Wunsch implementieren. Aber auch dieses gilt wieder nur für größere Anwendungen, da hier dieser Fall wahrscheinlicher auftritt, als bei einem kleinen Tool, welches ich als Entwickler nur für mich selber zusammenstricke.
Ein häufiges Argument, welches ebenfalls oft angewandt wird: Expression Blend ist zwar toll, kostet aber auch entsprechend. Ein kurzer Blick auf eine Homepage die etwas mit kriegerischen Frauen zu tun hat, zeigt: Expression Blend schlägt mit über 500 Euronen zu Buche. Dies ist in der Tat ein Betrag, den sich ein Hobbyentwickler, oder jemand der OpenSource-Software entwickelt, kaum leisten kann, bzw. vielmehr will. Ist auch verständlich. Gehen wir hier also nicht von einem professionellen Rahmen aus (hier sollte dieser Betrag aufzutreiben sein), sondern wenden wir uns diesbezüglich den Hobbyentwicklern zu. Wo sind also die Alternativen. Ja, da gibt es den Aurora XAML Designer, der jedoch auch nicht kostenfrei ist (jedoch mit unter 200 Euro noch erträglich) und zudem auch nicht so wirklicht gut abschneidet (siehe Aurora XAML Designer Schnelltest).
Weitere Alternativen sind rar und oft finden sich nur kleinere Tools, die den einen oder anderen Schritt automatisieren oder vereinfachen. Hier muss also noch auf jeden Fall nachgebessert werden, denn der „kleine Entwickler“ muss sehr viel zu Fuß erledigen und verliert damit dann schon Zeit, die vielleicht besser in die Logik investiert wäre.
Es muss jedoch auch hinzugefügt werden, dass sich der Aufwand durchaus in Grenzen hält und man auch sehr schnell zu Ergebnissen kommt. Fakt ist jedoch, dass gewisse Schritte nicht gemacht werden wollen, wenn man ganz genau weiß, dass es grundsätzlich Tools gibt, die das viel schneller erledigen, oder es Alternativen gibt, die das auch für mich machen. Windows Forms eben. Und solange die Unterstützung auf diesem Gebiet nicht besser ist, wird sich WPF, vor allem in der großen Gemeinde, der „kleinen Entwickler“, nicht durchsetzen. Stattdessen werden weiterhin die Windows Forms zum Einsatz kommen. Da zählen die Vorteile die durch die WPF geboten werden, eigentlich nicht wirklich …
| | | 6 Kommentare
- 3987 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL |
Undo und Redo implementieren
12.03.08 - Entwicklung, Diskussionen, Patterns, .NET, Grundlagen, Base Framework, WPF, ASP.NET Beitrag von Norbert Eder| | Es kommt ja doch häufig vor, dass eine Anwendung ein Undo bzw. ein Redo unterstützen muss. Wird diese Funktionalität gefordert wird immer wieder nach einer Umsetzungsmöglichkeit gefragt. Hier eine kleine Lösung, die für diese Zwecke verwendet werden kann.
Hinweis: In diesem Beispiel werden keine Fehlerabfragen gemacht. Es empfiehlt sich, einen Ausführungsstatus zu integrieren, der das Verhalten entsprechend beeinflusst.
Design
Um diese Funktionalität umzusetzen, wird das Command-Pattern verwendet. Dieses eignet sich sehr gut dazu, Aktionen auszuführen und diese auch wieder zurück zu nehmen. Erweitert wird das Command-Pattern um einen CommandManager, der für die Ausführung und Verwaltung der einzelnen Commands zuständig ist.
Implementierung
Zuerst wird eine Basisklasse für den Command implementiert, welche die Methoden Execute(), Undo und Redo zur Verfügung stellt.
public abstract class Command
{
public abstract void Execute();
public abstract void Undo();
public abstract void Redo();
}
Als weiteren Schritt wird der CommandManager implementiert. Dieser ist in diesem Fall ein Singleton (damit er nur einmal pro Instanz vorhanden sein kann) und bietet nach aussen hin die selbe Funktionalität wie ein Command an. Intern werden die einzelnen Commands jedoch in einem Stack behalten, um den Verlauf der einzelnen Commands nachvollziehen zu können. Darüber kann nun ein Undo bzw. ein Redo abgebildet werden.
public class CommandManager
{
#region Static Attributes
private static object _lockObject = new object();
private static CommandManager _instance = null;
#endregion Static Attributes
#region Attributes
private Stack<Command> _commandStack = new Stack<Command>();
private Stack<Command> _undoneStack = new Stack<Command>();
#endregion Attributes
#region ctor
private CommandManager() { }
#endregion ctor
#region Static Methods
public static CommandManager GetInstance
{
get
{
if (_instance == null)
{
lock (_lockObject)
{
_instance = new CommandManager();
}
}
return _instance;
}
}
#endregion Static Methods
#region Public Methods
public void Execute(Command command)
{
command.Execute();
_commandStack.Push(command);
}
public void Redo()
{
Command redoCommand = _undoneStack.Pop();
redoCommand.Redo();
_commandStack.Push(redoCommand);
}
public void Undo()
{
Command undoCommand = _commandStack.Pop();
undoCommand.Undo();
_undoneStack.Push(undoCommand);
}
#endregion Public Methods
}
Damit ist die eigentliche Implementierung bereits abgeschlossen und wir können zu einem ersten Test schreiten. Hierzu benötigen wir ein paar kleinere Klassen, die nicht wirklich etwas aufregendes machen.
Hier eine Klasse Person, die zwei Eigenschaften zur Verfügung stellt, anhand derer getestet wird. Zudem implementiert sie das Interface ICloneable (wird im nachfolgenden Command benutzt) und überschreibt die ToString-Methode.
public class Person : ICloneable
{
#region Properties
public String Firstname { get; set; }
public String Lastname { get; set; }
#endregion Properties
#region ICloneable Members
public object Clone()
{
Person p = new Person();
p.Firstname = this.Firstname;
p.Lastname = this.Lastname;
return p;
}
#endregion ICloneable Members
#region Overrides
public override string ToString()
{
return String.Format("{0}, {1}", Lastname, Firstname);
}
#endregion Overrides
}
Als nächsten Schritt müssen wir noch einen konkreten Command implementieren, der eine Aktion durchführt. Dieser wird sich lediglich ein wenig mit den Eigenschaften der Person spielen:
public class PersonCommand : Command
{
private Person _person;
private Person _personStateBefore;
public PersonCommand(Person person)
{
_person = person;
}
public override void Execute()
{
_personStateBefore = _person.Clone() as Person;
_person.Firstname = "Norbert";
_person.Lastname = "Eder";
}
public override void Undo()
{
_person.Firstname = _personStateBefore.Firstname;
_person.Lastname = _personStateBefore.Lastname;
}
public override void Redo()
{
Execute();
}
}
Wichtig ist an dieser Stelle nur, dass sich der Command den ursprünglichen Status des übergebenen Objektes merkt und somit eine Undo bzw. Redo-Funktionalität anbieten kann.
Schlussendlich ein Stück Code, welches bei mir in einer Konsolen-Anwendung direkt in der static void Main ausgeführt wird:
CommandManager manager = CommandManager.GetInstance;
Person p = new Person();
p.Firstname = "<not set>";
p.Lastname = "<not set>";
Console.WriteLine(
String.Format("Before first execution: " + p.ToString()));
manager.Execute(new PersonCommand(p));
Console.WriteLine(
String.Format("After first execution : " + p.ToString()));
manager.Undo();
Console.WriteLine(
String.Format("After undo : " + p.ToString()));
manager.Redo();
Console.WriteLine(
String.Format("After redo : " + p.ToString()));
Console.Read();
Und nun möchte ich das Ergebnis nicht vorenthalten:
Fazit
Wie zu sehen ist, ist ein Undo bzw. Redo-Mechanismus sehr einfach zu implementieren. Abhängig der Umgebung in welcher diese Methode zu tragen kommt, müssen eventuell weitere Mechanismen eingefügt werden.
| | | 9 Kommentare
- 2580 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL | Zurück Weiter
|
|
|
|
|
|
|