Aus Linux-Magazin 02/2009

C#-Entwicklung unter Linux - Teil 3

© boing, Photocase.com

Seit dem zweiten Teil der C#-Workshop-Serie im Linux-Magazin hat sich in der Mono-Welt etwas getan. Dieser Artikel gibt einen Überblick über die wichtigsten Neuerungen und führt praktisch Objektserialisierung und Webservices vor .

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.

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.

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).

Listing 1:
»simpleXML«

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 }

Methoden zur XML-Ausgabe

Die Klasse besitzt zwei Konstruktoren: einen zur Initialisierung der privaten Variablen, den anderen zum Laden der notwendigen Daten aus einer Datei. Der erste sollte selbsterklärend sein, der zweite greift auf die Dienste einer privaten Funktion »loadFromFile()« zurück. Daneben gibt es noch die Funktion »saveToFile()«, die das Objekt ins XML-Format überführt und in eine Datei schreibt.

Die Methode »saveToFile« (Listing 1, Zeile 14) erzeugt zunächst einen passenden »XmlTextWriter«. Die folgenden Codezeilen teilen ihm den Namen der Ausgabedatei sowie die passende Zeichenkodierung (»iso-8859-1«) mit. Zeile 18 weist ihn an, die verschiedenen Ebenen der Ausgabe zwecks besserer Lesbarkeit einzurücken. Dann schreibt die Methode den XML-Header und zur Dokumentation des XML-Code den Kommentar »Ein einfaches XML-Beispiel« in die Datei.

Es folgt die Ausgabe der Daten, eingeschlossen durch das »simpleXML«-Tag. Dieses wird mit Hilfe von »WriteStartElement()« ausgegeben. Man sollte sich dabei zur Regel machen, diesem Befehl auch immer das entsprechende »WriteEndElement()« folgen zu lassen – im Beispiel sorgt es dafür, dass »</simpleXml>« den Ausgabestrom abschließt.

Zwischen dem Start- und dem End-Element steht die XML-Darstellung der Daten. Ihre Ausgabe folgt dem beschriebenen Muster: Sie beginnt wieder mit einem Startelement. Dann weist der Code dem Element ein Attribut zu, das aus einem Namen sowie dem zugehörigen Wert besteht. Der ist natürlich ein String – im Falle von »intSecret_« und »doubleSecret_« fehlt also noch die Umwandlung in das String-Format. In der XML-Ausgabe wählt Mono automatisch die verkürzte Schreibweise, da etwa im Fall von »myIntSecret« außer dem Attribut keine Daten vorhanden sind.

Rauschen filtern

Die Methode »loadFromFile()« liest nun die XML-Datei mit dem »XmlTextReader«-Konstruktor wieder ein. Danach iteriert das Programm über alle Knoten des XML-Dokuments. Ein Switch-Statement macht den Programmablauf von der Art des gefundenen Elements abhängig. Das Programm reagiert nur auf die Daten-tragenden Knoten. Das Default-Statement ignoriert alle anderen Elemente.

Ist ein Tag, etwa mit Namen »myIntSecret«, gefunden, fragt das Programm nach dem Wert seines Attributs und wandelt es in den entsprechenden Zieltyp um. Zu guter Letzt speichert es den Wert einfach in der Zielvariablen. Das Hauptprogramm ist entsprechend kurz (Listing 2). Der Code erzeugt ein »simpleXML«-Objekt und initialisiert die privaten Variablen. Danach überführt »saveToFile()« das Objekt in sein XML-Format. Listing 3 zeigt das Ergebnis.

Ein zweites »simpleXML«-Objekt liest die Datei nun wieder ein und initialisiert seine Variablen mit den darin enthaltenen Informationen. Schließlich gibt die »printSecrets()«-Funktion diese Informationen aus, um deren korrekte Wiederherstellung zu überprüfen. Die Ausgabe sieht dann so aus:

intSecret_ = 1
doubleSecret_ = 2
stringSecret_ = drei

Damit ist ein Runtime-Objekt persistent gemacht, also in ein äquivalentes XML-Format überführt und wieder aus diesem geladen.

Listing 2:
Hauptprogramm

01   class Hauptprogramm
02   {
03     public static void Main(string[] args)
04     {
05       simpleXML myXmlObject = new simpleXML(1, 2.0, "drei");
06       myXmlObject.saveToFile("hello.xml");
07 
08       simpleXML myXmlObject2 = new simpleXML("hello.xml");
09       myXmlObject2.printSecrets();
10     }
11   }

Listing 3:
»hello.xml«

01 &lt;?xml version="1.0" encoding="iso-8859-1"?&gt;
02 &lt;!--Ein einfaches XML Beispiel--&gt;
03 &lt;simpleXml&gt;
04   &lt;myIntSecret value="1" /&gt;
05   &lt;myDoubleSecret value="2" /&gt;
06   &lt;myStringSecret value="drei" /&gt;
07 &lt;/simpleXml&gt;

Es geht auch einfacher

Für den erzielten Zweck, drei Variablen auf der Platte zwischenzuspeichern, erscheint die Methode allerdings reichlich kompliziert. XML hat zwar den Vorteil, sich leicht parsen und im Notfall auch mit einem Texteditor bearbeiten zu lassen. Statt eines einzelnen Zeichens verbraucht das Format aber etwa im Fall von »intSecret_« ganze 25 Zeichen. Man erkauft sich das intuitiv zugängliche Format also mit einem riesigen Overhead und erheblichem Programmieraufwand. C# bietet einen Ausweg, den dieser Artikel am Obst-Beispiel des letzten Artikels demonstriert. Teil 2 dieser Workshop-Reihe [1] hatte Äpfel und Birnen mit eigenen Variablen auf der Basis einer abstrakten Obst-Klasse erstellt und in einen »List<Obst>«-Container sortiert. Allein schon wegen der in diesem Beispiel enthaltenen Vererbungshierarchien sollte klar sein, dass es sich um wesentlich schwieriger zu serialisierende Objekte handelt.

Umso erstaunlicher ist es, wie einfach sich Persistenz unter C# mit Bordmitteln erreichen lässt: Es genügt, eine Klasse (und ihre Eltern) mit dem so genannten Attribut »[Serializable()]« zu kennzeichnen (Listing 4). Hier ist nicht der gesamte Code der Applikation wiedergegeben, sondern nur die relevanten Ausschnitte. Die Listings sind aber komplett auf der Website des Linux-Magazins zu finden [6].

Listing 4:
Serialisierung

01 using System.Runtime.Serialization;
02 
03 // [...]
04 
05 [Serializable()]
06 public class Apfel: Obst
07 {
08   public Apfel()
09     :base(2.0)
10     { /* nothing */ }
11 
12   public uint ZahlDerKerne
13     { get; set; }
14 }

Das Hauptprogramm (Listing 5) erzeugt ein »obstDrucker«-Objekt. Statt es aber direkt zu sortieren, serialisiert der Beispielcode es zunächst und lädt dann die gespeicherten Informationen in ein neues »obstDrucker«-Objekt. Erst jetzt stößt das Programm die Serialisierung an und gibt den Inhalt des Objekts aus.

Listing 5:
Hauptprogramm

01 class Hauptprogramm
02 {
03   public static void Main(string[] args)
04   {
05     Console.WriteLine("Vor der Serialisierung:");
06     ObstDrucker opr = new ObstDrucker();
07 
08     Console.WriteLine("Unsortiert:");
09     opr.print();
10 
11     // Serialisierung
12     FileStream fstream = new FileStream("obstDrucker.bin", FileMode.Create);
13     BinaryFormatter bformat = new BinaryFormatter();
14     try  {
15       bformat.Serialize(fstream, opr);
16     }
17     catch (SerializationException e) {
18       Console.WriteLine("Fehler bei der Serialisierung: " + e.Message);
19       throw;
20     }
21     finally {
22       fstream.Close();
23     }
24 
25     // De-Serialisierung
26     ObstDrucker opr2 = null;
27     FileStream fstream2 = new FileStream("obstDrucker.bin", FileMode.Open);
28     try {
29       opr2 = (ObstDrucker) bformat.Deserialize(fstream2);
30     }
31     catch (SerializationException e) {
32       Console.WriteLine("Fehler bei der De-Serialisierung: " + e.Message);
33       throw;
34     }
35     finally {
36       fstream2.Close();
37     }
38 
39     Console.WriteLine("nNach der De-Serialisierung:");
40     Console.WriteLine("Sortiert:");
41     opr2.sortiereObst();
42     opr2.print();
43   }
44 }

Zum ersten Mal im Lauf dieses Tutorials findet eine systematische Fehlerbehandlung statt. Try-Blöcke schließen anfälligen Code ein, eventuell aufgetretene Ausnahmen behandelt der dazugehörigen Catch-Block. Die Ausgabe des Programms zeigt Listing 6.

Listing 6: Test der
Serialisierung

01 Vor der Serialisierung:
02 Unsortiert:
03 Ich bin Obst vom Typ Apfel und der Groesse 6,53
04 Ich bin Obst vom Typ Birne und der Groesse 2,67
05 Ich bin Obst vom Typ Apfel und der Groesse 6,63
06 Ich bin Obst vom Typ Birne und der Groesse 6,83
07 
08 Nach der De-Serialisierung:
09 Sortiert:
10 Ich bin Obst vom Typ Birne und der Groesse 6,83
11 Ich bin Obst vom Typ Apfel und der Groesse 6,63
12 Ich bin Obst vom Typ Apfel und der Groesse 6,53
13 Ich bin Obst vom Typ Birne und der Groesse 2,67

Auch damit ist nun also Objektpersistenz erreicht, allerdings trotz der komplexeren Datenstruktur mit erheblich weniger Aufwand als im XML-Beispiel. Ein weiterer Vorteil ist, dass die Daten in diesem Beispiel im Binärformat gespeichert sind, was den Overhead gegenüber XML erheblich reduziert. Man sollte hieraus die Lehre ziehen, bei allen Programmieraufgaben immer erst einmal in Monos Standardbibliothek zu schauen.

Kommunikation

Zu guter Letzt folgt ein Beispiel für die Kommunikation zwischen zwei Programmen. Bei Webservices geht es darum, einen Remote Procedure Call mit Hilfe eines XML-basierten Protokolls (SOAP, Simple Object Access Protocol) zu implementieren. Die Kommunikation erfolgt dabei meistens via HTTP.

Die Grundlagen von Webservices können ganze Bücher füllen und sollen deshalb hier ausgespart bleiben. Die Verwendung in C# gestaltet sich aber gewohnt einfach. Im folgenden Beispiel soll eine “Integer-Fabrik” Arrays mit Integerzahlen produzieren, die ein anderes Programm dann sortiert zurückliefert. Listing 7 zeigt die Sortierfunktion.

Listing 7:
Sortierfunktion

01 using System;
02 using System.Collections.Generic;
03 using System.Runtime.Serialization;
04 using System.Web.Services;
05 using System.Linq;
06 
07 [WebService(Description="Webservice for Linux Magazine")]
08 public class arraySorter: WebService {
09   [WebMethod(Description="Sorting of an Integer Array")]
10     public void sort(ref int[] intArray){
11     Array.Sort(intArray);
12   }
13 }

Es reicht also, in einer als »WebService« gekennzeichneten Klasse eine passende »WebMethod()« zu definieren, um auf sie von außen zuzugreifen. Das folgende Kommando übersetzt den Programmcode:

gmcs /t:library /r:System.Web.Services arraySorter.cs 

Es entsteht eine DLL-Datei, die der Programmierer in das Unterverzeichnis »bin« verschiebt. Startet er den Mono-eigenen Webserver »xsp2« im selben Verzeichnis (oberhalb von »bin«), ist die Seite unter folgender Adresse erreichbar:

http://localhost:8080/arraySorter.asmx

Sie zeigt alle Details des Webservice und verschafft Zugriff auf automatisch generierten Code dieser Klasse (siehe Abbildung 3). Die Datei »arraySorter.asmx« erschöpft sich in nur einer Zeile:

&lt;%@ WebService Language="c#" Class="arraySorter,arraySorter" %&gt; 

Durch sie erfährt Mono, in welcher DLL es nach welcher Klasse suchen muss. Im Beispiel heißen beide »arraySorter«.

Abbildung 3: Mono generiert allen notwendigen Code zum Zugriff auf einen Webservice automatisch.

Abbildung 3: Mono generiert allen notwendigen Code zum Zugriff auf einen Webservice automatisch.

Als Nächstes lädt man den Code von der obigen Webseite herunter und speichert ihn unter dem Namen »arraySorterProxy.cs«. Sie enthält einen Funktionsrumpf (Stub), der transparenten Zugriff auf die Methode des anderen Prozesses erlaubt. Dem aufrufenden Programm bleibt somit verborgen, ob die Berechnung lokal oder in einem anderen Prozess abläuft. Bleibt nur noch, das passende Hauptprogramm zu erstellen (Listing 8).

Listing 8:
»IntArrayFactory«

01 using System;
02 using System.IO;
03 using System.Collections.Generic;
04 using System.Runtime.Serialization;
05 using System.Runtime.Serialization.Formatters.Binary;
06 using System.Linq;
07 
08 /*
09  * This class produces arrays of random int values
10  * and sends them to a remote system for sorting.
11  */
12 class IntArrayFactory {
13   public static void intProduction() {
14     for(int i=0; i&lt;10; i++) {
15       // Create an array of random numbers
16       int[] probe = new int[ARRAYSIZE];
17       Random rg = new Random();
18 
19       Console.WriteLine("Before sorting");
20       for(int j=0; j&lt;ARRAYSIZE; j++) {
21         probe[j] = rg.Next(ARRAYSIZE);
22         Console.WriteLine("probe[{0}] = {1}", j,probe[j]);
23       }
24 
25       // Create the Webservice proxy
26       arraySorter arsort = new arraySorter();
27       arsort.sort(ref probe);
28 
29       // Print the resulting array
30       Console.WriteLine("After sorting");
31       for(int j=0; j&lt;ARRAYSIZE; j++) {
32         Console.WriteLine("probe[{0}] = {1}", j,probe[j]);
33       }
34     }
35   }
36 
37   public static void Main(string[] args) {
38     IntArrayFactory.intProduction();
39   }
40 
41   private const int ARRAYSIZE = 4;
42 }

In der Klasse »IntArrayFactory« produziert eine Schleife Arrays von zufälligen Integerwerten. Dann erzeugt der Code eine Instanz des Stub und übergibt ihr das Array zur Sortierung. Für den Programmierer besteht kein Unterschied zwischen einer lokalen und einer entfernten Funktion. Das Beispiel ist durchaus nicht trivial, aber die Implementierung in C# fällt trotzdem relativ einfach aus. Den Code übersetzt der Befehl:

gmcs /r:System.Web.Services main.cs arraySorterProxy.cs 

Die Datei »main.cs« enthält dabei den Code aus Listing 8. Die Ausgabe des Programms sieht zum Beispiel so aus:

Before sorting
probe[0] = 1
probe[1] = 0
probe[2] = 1
probe[3] = 3
After sorting
probe[0] = 0
probe[1] = 1
probe[2] = 1
probe[3] = 3

Bei der Ausführung ist darauf zu achten, dass »xsp2« (im Quellverzeichnis oberhalb von »bin«) abläuft.

Übrigens spielt auch hier wieder die Serialisierung eine Rolle – schließlich muss das Integer-Array erst einmal in eine passende Darstellung (in SOAP) übersetzt werden, bevor es zum anderen Programm gelangt. All dies passiert hinter den Kulissen, während der Programmierer nur eine passende »WebMethod()« bereitstellen muss. Es lohnt sich in diesem Zusammenhang, einen Blick auf die WSDL-Datei zu werfen, die den Webservice beschreibt und die über deren Webseite einsehbar ist, hier »http://localhost:8080/arraySorter.asmx«. Die Details sind unter [7] und [8] beschrieben.

Ausblick

Mit großen Schritten nähert sich bereits das Ende dieses Mono-Tutorials im Linux-Magazin. Weil das Erlernen einer Programmiersprache wie C# wenig nützt, wenn man nicht auch die verfügbaren Hilfsmittel kennt, soll es im vierten und letzten Teil um den reichen Schatz an Bibliotheken gehen, die dem Programmierer viele Standardaufgaben erleichtern. Bis dahin viel Spaß und Erfolg mit der neuen Mono-Version. (ofr)

Infos

[1] Rüdiger Berlich, Mono-Workshop, Teil 2: Linux-Magazin 12/2008, S. 102

[2] Monodevelop: [http://monodevelop.com]

[3] Installation von Monodevelop 2.0 Alpha 2: [http://monodevelop.com/Download_-_Unstable]

[4] Moonlight, eine Silverlight-Implementierung für Linux: [http://www.mono-project.com/Moonlight]

[5] Testseite für Moonlight 1.0: [http://www.designwithsilverlight.com/tutorials/photoGallery/gallery.html]

[6] Listings online: [https://www.linux-magazin.de/static/listings/magazin/2009/02/Mono]

[7] Webservice mit Mono: [http://www.mono-project.com/Writing_a_WebService]

[8] Zugriff auf den Webservice: [http://www.mono-project.com/Web_Services]

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 6 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben