Ein eigener Datentyp (Teil 6)

Im letzten Teil (siehe: Ein eigener Datentyp (Teil 5)) haben wir uns um die Konvertierung aus Standard-Datentypen gekümmert. In diesem Teil soll es nun um die überschriebenen Methoden der Basisklasse – Object – gehen. Hier müssen wir die Implementierung für drei Methoden vornehmen, „Equals(object)“, „GetHashCode()“ sowie „ToString()“. Beginnen wir mit der „Equals“-Methode. Diese ist eigentlich auch schon die „komplizierteste“ der drei genannten. Hier würde ich die folgende Implementierung vorschlagen:

public override bool Equals(object obj)
{
    return ((obj is Int24) && (Value == ((Int24)obj).Value)) || ((obj is int) && (Value == (int)obj));
}

Weiterlesen

Ein Webservice aufbauen und in einer Anwendung nutzen (Grundlegendes)

Webservices werden in der heutigen Zeit immer wichtiger und diese bieten auch für viele Applikation einige nette Dienste, wie z.B. die Validierung einer Seriennummer, abfragen von Updates und mehr. Aber was benötigt man hierfür? Ich verwende für diesen Fall in der Regel einen C# .NET SOAP-Service, der einen IIS sprich einen Windows-Server benötigt. Eine ebenfalls – wie ich finde – sehr gute Alternative ist ein Webservice in PHP mit z.B. NuSOAP, der ohne Windows-Server Systeme auskommt und deswegen auch in der Regel relativ beliebt ist. Und genau mit diesen beiden werden wir uns befassen. Zunächst werde ich im nächsten Teil den IIS-Webservice erläutern, wie dieser zu erstellen ist usw. und im folgenden Teil den PHP-Webservice. Im letzten anschließenden Abschlussteil werde ich einen der beiden referenzieren und nutzen (da bei beiden Services die Nutzung gleich ist und mir derzeit nur ein Linux-Server zur Verfügung steht, wird dies auf NuSOAP mit PHP hinauslaufen).

Aber was sind die Vor- und Nachteile eines solchen Services? Nun die Vorteile sind ganz klar, dass die Anwendung nur kontrollierte Dinge tut und auch die Validierung von Seriennummern etc. sicher abläuft. Natürlich sollte man die Verbindung zum Webservice auch noch per SSL absichern, aber dies ist ein eigenes Thema für sich. Es könnte aber gut sein, dass dies ebenfalls bald kommt. Einer der Nachteile ist mit Sicherheit, dass die Verbindung zum Service notwendig ist und somit eine Lokale- oder Ethernetschnittstelle vorhanden sein muss. Natürlich kann man dies aber auch umgehen und den Service mehr optional als erforderlich gestalten.

Die kleinen Tricks in C# / .NET

Unter C# bzw. dem .NET-Framework gibt es einige kleine Tricks, mit denen man den Sourcecode noch weiter optimieren kann. Aufgrund dessen, dass diese evtl. nicht jedem bekannt sind, werde ich hier nun einige die ich als nützlich erachte auflisten.

Inkrement sowie Dekrement Operator Position
Abhängig von der Position des Inkrement bzw. Dekrement Operators wird ein anderer Effekt ausgelöst. Sehen wir uns dies einmal im Code an, damit jeder weiß was ich meine.

int value = 0;
Console.WriteLine(value++); //Output wird 0 sein. 

value = 0;
Console.WriteLine(++value); //Output wird 1 sein.

Hier steht der Operator einmal vor und einmal hinter der Variable. Und dies führt zu unterschiedlichen Effekten. Hier gilt, wenn der Operator vor der Variable steht wird vor dem Zugriff das Inkrement / Dekrement durchgeführt. Steht es dahinter erst nach dem Zugriff. Weiterlesen

PowerShell Scripte in .NET Anwendungen

Die Windows PowerShell ist eine sehr leistungsfähige Konsole, die mit stark geprägten Befehlen daher kommt. Diese ermöglichen eine ausführliche Aktionsreichweite unter Windows-Systemen. Oft sind sehr ähnliche Anforderungen oder gar die Anforderung diese Scripte ausführen zu können auch an uns Entwickler gestellt. Nun mit der Hilfe vom Microsoft .NET 4.0 und der Assembly „System.Management.Automation.dll“ ist dies auf sehr einfachem Wege möglich (.NET 4.0 ist hier leider die minimal Version, zumindest bei der Installation über NuGET, die mir bis dato als einzige bekannt ist). Um dies nun nutzen zu können, sollten wir also zunächst über die Paket-Konsole von NuGET folgende Aktion ausführen:

Install-Package System.Management.Automation

Hiermit wird die bereits genannte Assembly in unser Projekt installiert. Im Weiteren können wir uns der implementierung widmen. Ich werde dies hier anhand einer Konsolenanwendung vornehmen. Es funktioniert jedoch natürlich auch unter WPF und WinForms sowie ASP. Für das folgende Beispiel werden noch zusätzlich folgende Using-Directives benötigt:

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;

Und anschließend (hier aufgrund der Konsolenanwendung statisch) können wir uns der Implementierung widmen. Weiterlesen

Ein eigener Datentyp (Teil 5)

Im letzten Teil (siehe: Ein eigener Datentyp (Teil 4)) haben wir die „Parsing“-Methoden implementiert. In diesem Teil wird es um die Methoden zur Konvertierung aus Standardtypen gehen. Unter Standardtypen verstehen sich folgende: byte, sbyte,  short, ushort, int, uint, long, ulong, float, double, decimal sowie string (welchen wir theoretisch bereits im letzten Teil implementiert haben). Beginnen wir also mit den beiden Byte-Typen.

public static Int24 ConvertFromByte(byte value)
{
    return new Int24(value);
}

public static Int24 ConvertFromSByte(sbyte value)
{
    return new Int24(value);
}

Nicht weiter kompliziert. Da ein Byte niemals außerhalb der Reichweite unseres Typen sein kann, benötigen wir keine weiteren Aktionen. Dies wird bei späteren Typen anders aussehen und auch beim UInt24 würde dies unter Umständen wegen den vorzeichenbehafteten Typen anders aussehen. Weiterlesen

Ein eigenes Event definieren und nutzen

Oft kommt es vor, dass nach dem Ausführen einer Aktion in einer Klasse andere Klassen darüber benachrichtigt werden müssen oder sollen. Hierfür gibt es in .NET Events, die bei einer bestimmten Aktion ausgelöst werden (z.B. wenn eine asynchrone Aktion durchlaufen wurde und die Daten da sind). Natürlich kann es sein, dass hier die vom .NET vorgegebenen Standardevents ausreichen, aber natürlich ist es auch möglich eigene zu definieren, denn nicht oft passen in ein fertiges .NET-Event unsere Parameter hinein. Das Ganze ist auch gar nicht mal aufwändig, denn wir müssen lediglich unseren Eventhandler definieren und das Event in unserer Klasse einbinden und natürlich irgendwo auslösen.

public delegate void CustomEventDefinitionForACustomAction(object sender, object data);

public class ExampleClass
{
    public event CustomEventDefinitionForACustomAction CustomEvent;

    public void CustomAction()
    {
        if (CustomEvent != null)
            CustomEvent.Invoke(this, new object());
    }
}

Das ist auch schon alles an Quellcode was hierfür nötig ist. Das „delegate“ definiert hierbei unseren Handler mit den Parametern. Eine Klasse, die sich anschließend auf dieses Event hängt muss eine Methode mit den gleichen Parametern bereitstellen. Das „object data“ kann natürlich hier frei definiert werden. In der Regel verwendet man hier eine spezielle „Event-Args“-Klasse. Ausgelöst wird im Beispiel das Event beim Aufrufen der „CustomAction“-Methode, nachdem es zuvor als „CustomEvent“ in der Klasse verfügbar gemacht wurde.

Ein eigener Datentyp (Teil 4)

Im letzten Teil (siehe: Ein eigener Datentyp (Teil 3)) haben wir die letzten Operatoren implementiert. In diesem Part geht es um die „Parsing“-Methoden. Diese Methoden sollen dazu dienen das Parsing von Strings zu ermöglichen. Hierfür gibt es an den Standarddatentypen die Statischen-Methoden „TryParse“ sowie „Parse“. Auch wir wollen nun diese Methoden implementieren und zur Verfügung stellen. Hierbei ist „TryParse“ quasi Exception sicher (hier werden die Exceptions gecatcht und anschließend ein false zurück gegeben). Beginnen wir mit den beiden Varianten der „TryParse“-Methode. Diese könnten wie folgt aussehen:

public static bool TryParse(string s, out Int24 result)
{
    return TryParse(s, NumberStyles.Integer, null, out result);
}

public static bool TryParse(string s, NumberStyles style, IFormatProvider formatProvider, out Int24 result)
{
    int output;
    bool canParse = Int32.TryParse(s, style, formatProvider, out output);

    if (!canParse || output > IntMaxValue || output < IntMinValue)
    {
        result = new Int24();
        return false;
    }

    result = new Int24(output);
    return true;
}

Während die kurze Fassung dieser Methode lediglich unsere längere aufruft, nutzt die ausführlich implementierte Fassung nur die „TryParse“-Methode des 32-Bit Integers. Zusätzlich werden hier allerdings noch unsere begrenzten Max- und Minwerte geprüft.   Weiterlesen

Ein eigener Datentyp (Teil 3)

Im letzten Teil (siehe: Ein eigener Datentyp (Teil 2)) haben wir uns um die Implementierung der Grund-Operatoren gekümmert. In diesem Teil wollen wir uns den Vergleichs- sowie Bitoperatoren wenden, welche ebenfalls eine entschiedene Bedeutung für Datentypen haben. Hierfür müssen wir uns jedoch zunächst darüber im Klaren sein, dass wir letztendlich nur eine Einschränkung eines Int32-Datentypes erstellen und deshalb erneut, wie auch bei den Teilen zuvor, von den bereits in Int32 implementierten Methoden Gebrauch machen können. Die hier wohl wichtigsten Operatoren sind jene, die uns die Gleicheit bzw. Ungleichheit bestätigen. Diese würden, da wir eh nur eine Integer-Spezifikation verwenden, wie folgt aussehen:

public static bool operator ==(Int24 value1, Int24 value2)
{
    return value1.Value == value2.Value;
}

public static bool operator !=(Int24 value1, Int24 value2)
{
    return value1.Value != value2.Value;
}

Auch hier ist wieder zu erkennen, dass man es sich als Entwickler oft sehr einfach machen kann. Wobei an dieser Stelle ebenfalls bedacht werden sollte, dass bei einem wirklich eigenen Typen der nicht eine so große Ähnlichkeit mit einem anderen bereits existierenden Typen hat, natürlich viel mehr Aufwand benötigt wird.  Weiterlesen

Singletons und ihre Nebeneffekte

Singletons sind leider ein heutzutage viel zu viel genutzter Weg, um einfach überall an die Instanz einer Klasse heranzukommen. Bei der Suche in diversen Suchmaschinen für C#-Implementierungen dieser Konstrukte findet man oft ähnliche Umsetzungen wie diese hier:

public sealed class SomeSingleton
{
    private static SomeSingleton _instance; 

    private SomeSingleton()
    { }

    public static SomeSingleton GetInstance()
    {
        if (_instance == null) 
            _instance = new SomeSingleton();

        return _instance;
    } 
}

Sieht zwar erstmal nicht sonderlich böse aus, aber es gibt da so einige Punkte, in dem diese alles andere als freundlich zum Entwickler sind. Was ist nun, wenn in Zukunft mehr als nur eine Instanz dieser Klasse nötig ist? Wie soll das sauber getestet werden, wenn die Reihenfolge von Tests nicht vorherbestimmt werden kann? Ist es immer Transparent wo diese Klasse verwendet werden kann?  Weiterlesen

Ein eigener Datentyp (Teil 2)

Im letzten Teil (siehe: Ein eigener Datentyp (Teil1)) haben wir uns mit dem Grundgerüst unseres Datentypen zufrieden gegeben. Diesmal sollen die Operatoren implementiert werden. Der wohl wichtigste Operator hierfür dürfte der „implicit“-Operator oder auch Zuweisungsoperator sein. Auch hier werden wir wieder zwischen einem normalen Integer-Wert und einem Byte-Array unterscheiden und zwei Implementierungen vornehmen. Trotz der enormen Wichtigkeit dieses Operators ist dieser dennoch sehr simpel zu implementieren.

public static implicit operator Int24(int value)
{
    return new Int24(value);
}

public static implicit operator Int24(byte[] value)
{
    return new Int24(value);
}

Wie im Sourcecode zu sehen wird nur eine neue Instanz eines 24-Bit Integers erzeugt und zurück gegeben. Da wir bereits die nötigen Konstruktoren implementiert haben, haben wir keinen Aufwand mehr mit dieser Methode.  Weiterlesen