Die bisherigen Beispiele dieser Artikelreihe [1] sind mit Hilfe von Emacs\' C#-Modus entstanden. Viele eingefleischte Linux-Programmierer werden mit dieser Lösung durchaus zufrieden sein. Wer allerdings ein größeres Programm mit vielen unabhängigen Modulen unter Mono/C# entwickeln will, wünscht sich vielleicht eine integrierte Entwicklungsumgebung nach Art von Visual Studio.
Die derzeit beste Wahl in diesem Bereich ist Monodevelop, das in Version 1.0 verfügbar ist [2]. Allerdings besitzt auch diese IDE noch einige Schwachstellen. Größtes Manko ist der fehlende Debugger-Support. Daneben mag manchen Anwender stören, dass die Codevervollständigung nicht den kompletten Sprachumfang von C# 3.0 abdeckt.
Dies und vieles mehr ist nun in der seit dem 21. November verfügbaren Version 1.9.1 (alias Monodevelop 2.0 Alpha 2) enthalten. Als Debugger unterstützt Monodevelop sowohl den MDB (Mono Debugger) für managed Code als auch für native Applikationen den Linux-Standard-Debugger GDB (Abbildung 1).
Abbildung 1: Monodevelop 2.0 Alpha 2 unterstützt das Debuggen von managed wie auch native Code und hat sich gegenüber Version 1.0 stark weiterentwickelt.
Für Nutzer einer aktuellen Open-Suse-Distribution gestaltet sich die Installation einfach. Unter [3] findet sich ein Knopf für einen One Click Install mittels Yast. Folgen man den Anweisungen, bekommt Yast zunächst ein neues Repository, dann erfolgt der Download der Pakete.
Dies klappte im Test auf zwei Systemen vorzüglich. Bei einem dritten, auf dem von Hand eine neue Mono-Version installiert war, führte die Methode aber zum Desaster. Nicht nur deshalb sei darauf hingewiesen, dass Monodevelop in der Version 1.9.1 noch explizit als "unstable" gekennzeichnet ist. Wer also keine Alpha- (nach Meinung des Autors aber eher Beta-) Version des Pakets verwenden möchte oder seine existierende Installation nicht gefährden will, sollte auf das Erscheinen der endgültigen Version 2.0 sowie deren Integration in die verwendete Linux-Distribution warten.
Im Test hatte die Installation von Monodevelop 1.9.1 mit Yast auch noch den angenehmen Nebeneffekt, eine existierende Mono-Installation in Version 1.9.1 (der Standard unter Open Suse 11.0) auf Version 2.0.1 zu aktualisieren.
Seit dem 6.10.2008 ist nun endlich die finale Version 2.0 von Mono verfügbar - der am 23. Oktober gleich eine Bugfix-Release folgte. Damit erringt Mono eine Vielzahl aktueller Fähigkeiten des Dotnet-Framework. So sind etwa die ADO.NET- und ASP.NET-2.0-APIs implementiert, Gleiches gilt für Windows.Forms 2.0. Hervorzuheben ist auch die Unterstützung der Language Integrated Query (LINQ). Dahinter verbirgt sich die Möglichkeit, Datenstrukturen im Stil einer Datenbank-Query abzufragen.
RIA mit Moonlight
Schließlich sei noch darauf hingewiesen, dass auch von der Silverlight-Implementierung Moonlight die erste Beta erschienen ist. Silverlight ist der Microsoft-Konkurrent zu Adobe Flash, Moonlight die entsprechende Open-Source-Implementierung [4]. Ein kurzer Test (nach dem Update auf Mono 2.0.1) mit einer der Moonlight-Testseiten [5] zeigte zunächst einen Download-Link für Microsoft Silverlight - Moonlight war zu diesem Zeitpunkt noch nicht installiert. Ein Klick auf den Link führte dann aber auf die Moonlight-Downloadseite - offensichtlich wird hier automatisch das Betriebssystem des Users geprüft.
Es folgt die Installation des entsprechenden Firefox-Plugins, woraufhin die Photogalerie-Anwendung problemlos funktioniert (Abbildung 2). Es scheinen übrigens fast alle der 44 Testseiten bereits gut unterstützt zu sein - es tut sich also viel in Mono-Land.
Abbildung 2: Die Photogalerie-Beispielanwendung [5] für Microsofts Silverlight funktioniert auch mit dem Mono-Pendant Moonlight problemlos.
Back to Business
Zurück zum eigentlichen C#-Tutorial. Es beginnt mit Objektpersistenz und wendet sich dann der Kommunikation mittels Webservices zu. Laut Wikipedia steht Persistenz für "das langfristige Fortbestehen einer Sache". Die Informatik verwendet den Begriff, wenn es um die Zwischenspeicherung oder Sicherung von Datenstrukturen geht. Der Programmierer muss also ein Speicherformat definieren, das sich dazu eignet, Daten auf der Festplatte zu speichern. Häufig findet XML hierfür Verwendung - die Extensible Markup Language. Ein Integerwert könnte nach dieser Methode etwa so gespeichert werden:
<myInt>3</myInt>
Das folgende, kürzere Format macht von XML-Attributen Gebrauch:
<myInt value="3"/>
Man könnte nun auf die Idee kommen, eine ganze Klasse in das XML-Format zu überführen und ein neues Objekt auf Basis dieser Beschreibung zu erzeugen. C# respektive Mono bringen alle notwendigen Funktionen bereits mit.
Als Beispiel soll eine Klasse »simpleXML« dienen, die drei private Variablen »intSecret_«, »doubleSecret_« und »stringSecret_« besitzt. Es gilt nun, diese in ein XML-Format zu übertragen und daraus anschließend wieder ein Objekt der ursprünglichen Klasse zu erzeugen (siehe Listing 1).
01 class simpleXML {
02 // sets all parameters
03 public simpleXML (int intSecret, double doubleSecret, string stringSecret) {
04 this.intSecret_ = intSecret;
05 this.doubleSecret_ = doubleSecret;
06 this.stringSecret_ = stringSecret;
07 }
08
09 // loads all parameters from file
10 public simpleXML (string fileName) {
11 this.loadFromFile(fileName);
12 }
13
14 public void saveToFile(string fileName) {
15 // Create an XML writer and set some variables
16 XmlTextWriter xmlWriter = new XmlTextWriter(fileName, Encoding.GetEncoding("iso-8859-1"));
17 xmlWriter.Formatting = Formatting.Indented;
18 xmlWriter.IndentChar = ' ';
19
20 // Emit the XML header
21 xmlWriter.WriteStartDocument();
22 // Emit a descriptive comment
23 xmlWriter.WriteComment("Ein einfaches XML-Beispiel");
24
25 // Emit an "XML frame"
26 xmlWriter.WriteStartElement("simpleXml");
27
28 // Emit the integer secret
29 xmlWriter.WriteStartElement("myIntSecret");
30 xmlWriter.WriteAttributeString("value", intSecret_.ToString());
31 xmlWriter.WriteEndElement();
32
33 // Emit the double secret
34 xmlWriter.WriteStartElement("myDoubleSecret");
35 xmlWriter.WriteAttributeString("value", doubleSecret_.ToString());
36 xmlWriter.WriteEndElement();
37
38 // Emit the string secret
39 xmlWriter.WriteStartElement("myStringSecret");
40 xmlWriter.WriteAttributeString("value", stringSecret_);
41 xmlWriter.WriteEndElement();
42
43 // End of XML frame
44 xmlWriter.WriteEndElement();
45
46 // Finalize the document
47 xmlWriter.WriteEndDocument();
48
49 // Flush out and close the document
50 xmlWriter.Flush();
51 xmlWriter.Close();
52 }
53
54 public void loadFromFile(string fileName) {
55 // Create an XML reader
56 XmlTextReader xmlReader = new XmlTextReader(fileName);
57
58 // Extract all data
59 while(xmlReader.Read()) {
60 XmlNodeType nodeType = xmlReader.NodeType;
61
62 // Check the node type
63 switch(nodeType) {
64 case XmlNodeType.Element:
65 switch (xmlReader.Name) {
66 case "myIntSecret":
67 xmlReader.MoveToNextAttribute();
68 intSecret_ = Convert.ToInt32(xmlReader.Value);
69 break;
70 case "myDoubleSecret":
71 xmlReader.MoveToNextAttribute();
72 doubleSecret_ = Convert.ToDouble(xmlReader.Value);
73 break;
74 case "myStringSecret":
75 xmlReader.MoveToNextAttribute();
76 stringSecret_ = xmlReader.Value;
77 break;
78 default:
79 continue;
80 }
81
82 break;
83 }
84
85 }
86 }
87
88 public void printSecrets() {
89 Console.WriteLine("intSecret_ = {0}", intSecret_);
90 Console.WriteLine("doubleSecret_ = {0}", doubleSecret_);
91 Console.WriteLine("stringSecret_ = {0}", stringSecret_);
92 }
93
94 private int intSecret_=0;
95 private double doubleSecret_=0.0;
96 private string stringSecret_="null";
97 }
|