Jan 232015
 

Beim Schreiben von Unittests bin ich mal wieder darüber gestolpert, dass jemand speziell für die Unittests Getter und Setter angelegt hat, da er auf die privaten Variablen der Klasse nicht zugreifen konnte. Im Prinzip hat er damit für seinen Unittest die internen Variablen dann über den Zugriffsmodifizierer public dann doch wieder sichtbar gemacht, wenn auch nur indirekt. Das ist so natürlich nicht gewollt, denn sonst hätte man gleich den Zugriff auf die internen Variablen erlauben können. Vielleicht noch kurz zur Erklärung: unsere Unittests sind immer in eigenständige Assemblies ausgelagert, sodass wir von Außen auf die zu testenden Klassen zugreifen müssen. Das macht auch Sinn, da die Unittests in dem Kompilat nicht enthalten sein sollen. Wie kann man das Problem also lösen?

Das .NET Framework bietet dafür das Attribut InternalsVisibleTo aus dem Namespace System.Runtime.CompilerServices an. Um nun die internal Methoden, Variablen und Properties freizugeben, wird das Attribut in die AssemblyInfo.cs des zu testenden Projekts eingefügt.

Danach kann man mit dem im InternalsVisibleTo-Attribut angegeben Assembly seine Unittests auf den Klassen durchführen ohne alles Zugriffsmodifizierer auf public zu setzen.

Solltet ihr eure Assemblies signieren, muss das einzufügende Attribut um den Public Key des zugreifenden Assemblies erweitert werden. Zusätzlich muss außerdem das zugreifende Assembly signiert werden. Der Eintrag in der AssemblyInfo.cs sieht dann so aus:

Das ist natürlich nur eine Herangehensweise, aber – wie ich finde – eine doch recht elegante. Wie macht ihr das in euren Unittests? Habt ihr eine ähnliche Vorgehensweise oder schreibt ihr einfach gar keine ;-)?

Dez 082014
 

Bei der Entwicklung von Unittests für mein privates Windows Store und Windows Phone Projekt bin ich bei der Konvertierung der alten Unittests für die Portable Class Library (PCL), die in dem Projekt verwendet wird, darüber gestolpert, dass auf einmal das „ExpectedException“ Attribut nicht mehr gefunden wird. Dieses Attribut verwendete man in den Unittests, um Tests zu kennzeichnen, die eine Exception werfen müssen. So richtig sauber war das allerdings irgendwie noch nie, da man eigentlich die einzelnen Bedingungen mittels „Assert“ geprüft hat. Es ist also nur konsequent, dass das Attribut mittlerweile entfernt wurde und durch eine entsprechende Methode in der Assert-Klasse ersetzt wurde. Folgendes kleines Beispiel zeigt die Verwendung der Methode „ThrowsException“:

Simpel, oder? Hat mich allerdings trotzdem etwas Zeit gekostet, da ich mit dieser Änderung erst mal nicht gerechnet habe.

Nov 242014
 

Habt ihr schon einmal das Problem gehabt, dass ihr im laufenden Programm Assemblies eines anderen Programmes nachladen wollt? Evtl. eine API, die bereits vorher in einem anderen Verzeichnis installiert wurde? Es gibt dafür drei Möglichkeiten:

  1. Kopieren der benötigten Assemblies in der Zielordner der Anwendung
  2. Installation der Assemblies in den GAC (Global Assembly Cache)
  3. Einbinden eines eigenen ResourceEventHandler, der die Assemblies aus einem entsprechenden Verzeichnis lädt

Hier soll es um die letzte Möglichkeit gehen. In der Klasse AppDomain kann man über das statische Property CurrentDomain die aktuelle Application Domain des laufenden Programmes abfragen. In diesem Objekt kann man dann einen ResolveEventHandler unter AssemblyResolve registrieren, der dann das Laden der Assemblies übernimmt. Hört sich kompliziert an, ist es aber letztendlich nicht. Nachfolgendes Beispiel zeigt, wie man einen ResolveEventHandler registriert und wie der EventHandler aufgebaut ist. Dabei wird beim Registrieren der Pfad aus der Registry ausgelesen:

 

Nov 132014
 

Ja! Richtig gelesen: Microsoft hat sich dazu entschlossen das.NET zukuünftig als Open Source Software zur Verfügung zu stellen und das nicht unter irgendeiner dubiosen Lizenz, sondern unter der sehr freizügigen MIT-Lizenz. Der Quellcode wird außerdem auf GitHub verwaltet und Pull-Requests werden auch ermöglicht. Jeder kann also in Zukunft am .NET Kern mitarbeiten. Dieser Schritt hat sich bereits schon länger abgezeichnet. Man hat die .NET Foundation gegründet, die sich in Zukunft mit der Weiterentwicklung von .NET befassen wird, die neue Compiler Plattform „Roslyn“ wurde direkt als Open Source freigegeben, F# ist Open Source und der Sourcecode des .NET Frameworks ist unter http://referencesource.microsoft.com auch schon länger einsehbar.
Neben der Open Source Strategie sieht man, dass .NET auf immer mehr Plattformen läuft. Dank Xamarins Mono ist .NET nämlich fast überall zu Hause – sei es iOS, Android, Linux, Mac OS X, den Raspberry Pi, die Nintendo Wii, die Playstation, die Xbox sowieso – um nur mal einige zu nennen. Mittlerweile wird auch der Cross-Platform Ansatz auch innerhalb Visual Studio immer besser unterstützt, d.h. die Entwicklung für Android, iOS, Windows Phone und Desktop Apps wird immer einfacher.
Für mich steht seit einiger Zeit schon fest, dass .NET irgendwie zum neuen Java geworden ist. Zwar gilt der alte Leitspruch von Java ,“Write once, run everywhere“, nicht in .NET, da man immer noch plattformabhängige Teile implementieren muss, aber man kann große Teile der Business Logik bereits auslagern und muss nur noch wenig neu implementieren und, was meiner Meinung nach viel wichtiger ist, warten. Die Sprache ist immer noch lebendig, d.h. sie wird fortwährend weiterentwickelt und hat sich dadurch bereits einen Vorsprung gegenüber dem langsamen Java Community Process erarbeiten können (man denke mal an die lange Hängepartie mit den Lambda-Ausdrücken :-/).
Ich freue mich jedenfalls über die neue Offenheit von Microsoft und bin gespannt, wie es weiter geht. Vielleicht wird es ja irgendwann mal ein Open Source Windows geben ;-)?

Okt 272014
 

Hattet ihr auch schon einmal das Problem, dass ihr in eurer Software eine Enumeration verwenden wolltet, aber eigentlich zwei Enumeration benötigt wurden, weil ein anderer Programmteil mehr Werte benötigt? Ich schon :-). In meinem Fall ging es um Messbereiche von unterschiedlichen Hardwaregeräten. Zum Beispiel besitzt Gerät A die Messbereiche „Low“ und „High“, während Gerät B die Messbereiche „Low“, „High“, „Medium“ und „Aux“. Der Entwickler soll in seinem Programm aber nicht mit der Hardwareabhängigkeit konfrontiert werden und wählt über den Namespace das entsprechende Gerät und damit auch die Implementierung der Enumeration.
Da „Low“ und „High“ die gemeinsamen Messbereiche abbilden, werden sie in der Hauptklasse verwendet, von der alle Erweiterungen dann ableiten. Der eigentliche Trick besteht aber darin, dass diese Klasse statische Klassenvariablen anbietet, die nur innerhalb dieser Klasse und ihrer Ableitungen initialisiert werden können. Überläd man außerdem noch die Operatoren kann man auch einfach die Werte miteinander vergleichen. Hier ein Beispiel, wie diese Klasse aussehen könnte:

Möchte man diese Klasse nun erweitern, braucht man nur eine neue Klasse anlegen, die von dieser Klasse ableitet und den Konstruktor der Basisklasse aufrufen. Hier das Beispiel für das oben genannte Gerät B:

Im Hauptprogramm kann man jetzt einfach eine Variable vom Typ „MeasurementRange“ deklarieren und die statischen Variablen der beiden Klassen zuweisen. Dabei ist es vollkommen egal, von welcher Klasse die statischen Variablen herkommen. Nachfolgend ein paar Zeilen Programmcode, die das auch noch verdeutlichen:

Für unsere Implementierung war das genau der richtige Ansatz. Solltet ihr das Extendable Enum in einem eurer Projekte einsetzen oder andere (elegantere?) Ansätze für das Problem haben, dann schreibt doch einen Kommentar. Würde mich freuen :-).

 

Durch die weitere Nutzung der Seite stimmst du der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen