Vorkonfigurierte Controls

Ich vermute, dass ausser mir eine ganze Reihe von .NET-Programmieren auch schon in folgender Situation waren: Man muss eine neue Form mit einer ganzen Reihe von Controls definieren im Designer, und für viele der Controls stehen eine Anzahl von Eigenschaften eigentlich schon von Beginn weg fest, und mit der Zeit wünscht man sich, der Designer würde – irgendwie! – diese Eigenschaften gleich beim Erzeugen der Objekte von selbst richtig setzen, so dass man das nicht für x Controls wieder und wieder von Hand selbst tun muss.

Ein Beispiel: Eine Firma arbeitet gewissen Normen punkto Buttons. Sie müssen alle dieselbe, festgelegte Grösse haben, und der Name sei abzuleiten vom Text des Buttons. Wie schön wäre es doch, wenn man dem Designer eine Funktion Erzeuge Standard-Button beibringen könnte, die nach Eingabe des Button-Textes den Button gleich so erzeugt?

Hier würde natürlich ein User Control Standard-Button auch helfen, aber wenn das Szenario nur etwas vielfältiger wird, wie im folgenden Beispiel, ist das kein geeignetes Mittel mehr:

Man portiert eine alte Applikation auf .NET und beginnt mit der Form nicht bei Null, sondern hat im Prinzip die Liste der Controls für die Form schon, als Tabelle in einer Textdatei, mit Namen, Typen und Längen, vom „alten“ Entwicklungs-System her. Es wäre doch schön, diese Tabelle irgendwie im Designer einlesen zu können und für jedes „alte“ Control ein entsprechendes .NET-Control zu erzeugen.

Wie viele Dinge im .NET-Framework geht ein solchermassen Code-gesteuertes Erzeugen von Controls im Designer ziemlich einfach, wenn man den „Kniff“ kennt:

Man schafft sich zuerst die Möglichkeit, eigenen Code im Designer-Kontext laufen zu lassen, z.B. indem man einen System.Windows.Forms.Design.ControlDesigner samt DesignerActionList implementiert, und kann anschliessend neue Controls mit Hilfe des aktiven IDesignerHost-Objekts ganz einfach erzeugen:

   IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
   Button b = (Button)designerHost.CreateComponent(typeof(Button), buttonName);
Advertisements
Veröffentlicht in Keine Kategorie. Schlagwörter: , . Leave a Comment »

Zugriff auf unterschiedliche Datenbank-Server

Vielleicht ist das, worüber ich hier schreibe, für Sie bereits ein alter Hut, weil es schon im Framework 2.0 eingeführt wurde, aber vielleicht kennen Sie es ja noch nicht, weil Microsoft die Sache nicht an die grosse Glocke hängt:

In unserem Entwicklungswerkzeug EMBASSY waren wir es gewohnt, mit Hilfe von ODBC generisch auf verschiedene Datenbank-Server zuzugreifen, konkret vor allem auf Microsoft SQL Server und Oracle. Das ist ja zum grossen Teil überhaupt der Witz einer Treiber-artigen Schnittstelle wie ODBC, dass Dinge abstrahiert werden und so eine weitgehend generische Programmierung möglich wird.

Umso überraschter waren wir damals bei einem Blick auf das .NET Framework 1.1, dass eine solche Abstraktions-Ebene nicht in Sicht war. Gemäss Microsoft das bevorzugte Mittel, um auf Datenbank-Server zuzugreifen: auf den jeweiligen Server zugeschnittene, spezifische eigene Klassen, also Klassen wie SqlConnection und OracleConnection, SqlCommand und OracleCommand, usw.

Auf der einen Seite sind solche massgeschneiderten Klassen natürlich hübsch, aber auf der anderen Seite eben ein Hindernis beim Versuch, ein Programm zu schreiben, dass via einfache Konfigurations-Angabe von einem Server-Typ auf einen anderen wechseln kann. Und ja, auch klar, dass Microsoft nicht unbedingt möchte, dass alle Programme ganz einfach vom hauseigenen SQL Server auf das Konkurrenz-Produkt Oracle umschaltbar sind, aber dass die Hürde dann gleich so gross herauskommt?

Glücklicherweise hatte Microsoft bereits bei der Version 2.0 des Framework ein Einsehen: Das Zauberwort heisst DbProviderFactory. Eine DbProviderFactory offeriert Methoden, wie man auf generische Weise zu Connection-Objekten, Command-Objekten usw. kommt.

Die Methode GetFactory der statischen Klasse DbProviderFactories dient dazu, eine DbProviderFactory zu beschaffen, wenn man den Namen des Providers kennt, also z.B. System.Data.OracleClient.

Natürlich geht es bei jedem nicht-trivialen Programm nicht komplett ohne das Wissen, auf welchem Typ Server man gerade arbeitet, denn es bleiben Unterschiede bei den unterstützten Datentypen, bei einigen SQL-Anweisungen wie z.B. CREATE TABLE, und bei den auftretenden Exceptions, um die man sich explizite kümmern muss, aber über weite Strecken wird der Code dank den „Factories“ tatsächlich frei von Fallunterscheidungen.

Veröffentlicht in Keine Kategorie. Schlagwörter: , . Leave a Comment »

Mehrfachvererbung

Vor einigen Wochen stand ich recht unerwartet vor einem trickreichen Design-Problem, bei dem es sich lohnen düfte, hier davon zu erzählen.

Für unsere im Entstehen begriffene neue .NET-basierte Programmierumgebung Triton wollte ich eine neue Control-Klasse definieren. Es ging darum, die Fokus-Steuerung, die Validierung und das Melden von Fehlern gegenüber der Standard-Klasse Form zu verbessern und zu generalisieren, und das bedeutete auch gewisse Erweiterungen bei der Funktionalität der Controls.

Also, an die Arbeit, und eine Basis-Klasse TritonControl definieren, welche die nötigen grundsätzlichen Erweiterungen und die Zusammenarbeit mit TritonForm enthält, und dann TritonTextBox, TritonCheckBox usw. davon ableiten…

Aber Moment mal: Wie soll das überhaupt gehen? Man kann der bestehenden Klasse System.Windows.Forms.TextBox ja keine neue Basis-Klasse TritonControl „unterjubeln“ bzw. sich in die Klassenhierarchie irgendwo zwischen Control und TextBox hineinzwängen. Auf der anderen Seite, gegen „oben“ in der Hierarchie, ist es zwar einfach, von TextBox eine TritonTextBox abzuleiten, aber so ergibt sich natürlich auch keine gemeinsame Basis-Klasse, sondern beim Ableiten von einem Dutzend .NET-Control-Klassen nur ein Dutzend typenmässig inkompatibler neuer Klassen, mit denen sich kein vernünftiges System bauen lässt.

Es gibt meiner Meinung nach nicht viel, was C++ der Sprache C# voraus hat, aber immerhin: In C++ wäre man jetzt hingegangen und hätte locker per Mehrfachvererbung die neue Klasse TritonTextBox eben von TextBox und TritonControl abgeleitet. Das ist so in C# nicht möglich.

Eine Analyse des Problems zeigte zwei mögliche Lösungen:

Erstens könnte man TritonControl von UserControl ableiten, und TritonTextBox wiederum von TritonControl. Ein solches Control würde dadurch zu einer Eingabemöglichkeit für einen Text, indem es zur Laufzeit dynamisch ein Child Control für sich vom richtigen Typ erzeugt, konkret eine System.Windows.Forms.TextBox, oder indem man im Designer statisch dem UserControl ein solches Child Control gibt.

Zweitens könnte man TritonTextBox von TextBox ableiten, aber zusätzlich mit einem Interface ITritonControl ausstatten.

Beim ersten Ansatz ist hauptsächlich unschön, dass man eine Menge Properties definieren muss in den von TritonControl abgeleiteten Klassen, damit deren Werte an die „inneren“, quasi an die echten Controls, weitergegeben werden können.

Beim zweiten Ansatz ist unschön, dass man das Interface mit einer ganzen Reihe von Methoden und Properties bei jedem abgeleiteten Control separat implementieren muss.

Nach einigen Überlegungen entschieden wir uns für den zweiten Ansatz. Das Implementieren des Interface ist zwar eine gewisse Fleissarbeit, aber dafür hat man sicher keinen Ärger mit dem Designer, für den eine TritonTextBox immer noch eine waschechte TextBox ist, mit der richtigen visuellen Darstellung, dem richtigen Design-Verhalten, und allen interaktiv spezifizierbaren Eigenschaften, für welche man die .NET-Controls so mag.

Veröffentlicht in Keine Kategorie. Schlagwörter: . Leave a Comment »

Programmiersprachen-Popularität

Wenn man wie die Megos im Moment von einer Programmiersprache (C++) auf eine andere (C#) wechselt als Basis für seine Applikationen, wäre es ab und zu ganz verlockend, etwas in Richtung einer Bestätigung zu bekommen, dass man tatsächlich auf das „richtige“ Pferd setzt.

Ich habe kürzlich einen Artikel gelesen, wo eine Statistik erwähnt wurde, welche die Beliebtheit von Programmiersprachen messen möchte, und bin der Sache nachgegangen, eben um zu sehen, wie es gemäss dieser Statistik um C# steht.

Es handelt sich um den sogenannten TIOBE Programming Community Index. Er wird offenbar ermittelt, indem in den populärsten Suchmaschinen nach dem Begriff <Programmiersprache> programming gesucht wird, konkret bei C# also nach C# programming und einer Reihe naher verwandter Suchbegriffe wie C sharp programming.

Die solchermassen 50 beliebtesten Programmiersprachen d.h. alle Hits für die 50 mit den meistens Hits bilden die 100%.

Man kann sich natürlich trefflich über die Genauigkeit von Resultaten streiten, die auf diese Weise zu ermitteln sind. Man könnte über ganz verschiedene Dinge meckern, z.B. die Beschränkung auf englische Suchbegriffe oder die Tatsache, dass eine Programmiersprache im Zentrum eines „Hype“ zwar auf eine Menge Hits kommt, aber dass deswegen noch lange nicht viel damit programmiert wird. Darüber hinaus dürften ältere Sprachen einen Bonus bekommen, weil einfach länger Zeit war, im Web etwas über sie zu veröffentlichen.

Aber immerhin, lustig ist so eine Statistik natürlich trotzdem: Im Juni 2008 steht C# an 8. Stelle, mit einem Anteil von knapp über 4%.

Nach meiner Beurteilung ist das ganz ordentlich für eine Sprache, die so jung ist. Wie man unter der Überschrift Long time trends auf der erwähnten Seite in einem Chart sehen kann, geht es zudem aufwärts mit C# – nicht spektakulär, aber stetig.

Ich schlage diese Statistik mal hinzu zu den guten Fortschritten beim bisherigen Arbeiten mit C# in der Megos und zur Tatsache, dass eine ganze Reihe anderer, vergleichbarer Schweizer Software-Häuser ihre „Next Generation“-Software mit .NET erstellt hat.

Veröffentlicht in Keine Kategorie. Schlagwörter: . Leave a Comment »