Seit heute gibt es die offizielle Windows 8 App von oopbase.de!
http://apps.microsoft.com/windows/de-DE/app/oopbase/1f7e83fb-97b5-4a53-92ed-76b1e2c7635e
Sofern ihr Windows 8 nutzt würde ich mich über eine Bewertung freuen
.
Seit heute gibt es die offizielle Windows 8 App von oopbase.de!
http://apps.microsoft.com/windows/de-DE/app/oopbase/1f7e83fb-97b5-4a53-92ed-76b1e2c7635e
Sofern ihr Windows 8 nutzt würde ich mich über eine Bewertung freuen
.
Heute möchte ich zeigen, wie man unter C# .NET eigene Attribute implementieren und verwenden kann.
Dazu zunächst die Definition eines Attributs von MSDN:
Attribute stellen eine effiziente Methode dar, um Deklarationsinformationen mit C#-Code (Typen, Methoden, Eigenschaften usw.) zu verknüpfen. Sobald das Attribut einer Programmentität zugeordnet ist, kann es zur Laufzeit mithilfe eines Verfahrens abgefragt werden, das als Reflektion bezeichnet wird.
Ein bekanntes Beispiel ist das Obsolete() Attribut. (Das Pendant in Java wäre @Deprecated)
|
1 2 3 4 5 |
[Obsolete("Bitte nicht mehr benutzen")] public void MeineMethode() { Console.WriteLine("Ich werde nicht mehr benötigt..."); } |
Wenn man also über der Signatur einer Methode ein Attribut definiert, dann kann dieses via Reflection ausgelesen und verarbeitet werden. In dem konkreten Fall von Obsolete() würde der Compiler nun eine Warnung ausgeben, dass die entsprechende Methode veraltet ist.
Die Implementierung:
Zunächst ist ein Attribut nichts weiter als eine Klasse, die von System.Attribute erbt. Die simpelste Form könnte also wie folgt aussehen:
|
1 2 3 4 |
public class AdditionalMethodInfo : System.Attribute { // } |
Wie der Klassenname verrät, soll ein Attribut implementiert werden, mit dem man zusätzliche Informationen über die jeweilige Methode erhält. Interessante Informationen wären evtl. das Erstellungsdatum sowie der Autor. Weiterhin möchten man vllt., dass man das Attribut ausschließlich über Methoden und nicht über Klassen setzen kann. Dazu wird die Klasse lediglich um zwei Properties sowie um ein eigenes Attribut erweitert:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
[System.AttributeUsage(System.AttributeTargets.Method)] public class AdditionalMethodInfo : System.Attribute { public string Author { get; set; } public DateTime CreationDate { get; set; } public AdditionalMethodInfo(string author, DateTime creationDate) { Author = author; CreationDate = creationDate; } } //Beispielklasse für möglichen Aufruf: public class Test { public int Nr { get; set; } public Test(int nr) { Nr = nr; } [AdditionalMethodInfo("Chuck Norris", DateTime.Parse("14.03.2013")] public bool Answer() { return Nr == 42; } } |
In diesem Fall hätte die Methode Answer() den Autor “Chuck Norris” und das Erstellungsdatum “14.03.2013″. Die im Konstruktor definierten Parameter werden beim Aufrufen des Attributs übergeben.
Die Auswertung:
Wie bereits erwähnt lassen sich die Attribute nun via Reflection auswerten. Wenn man nun das obige Beispiel aufgreift und man z.B. wissen möchte, wie viele Methoden der Klasse Test heute entwickelt wurden, könnte eine Auswertung wie folgt aussehen:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
class Analysis { static void Main() { PrintTodaysMethods(typeof(Test)); } private static void PrintTodaysMethods(System.Type t) { System.Attribute[] attributes = System.Attribute.GetCustomAttributes(t); int ctr = 0; foreach (System.Attribute attr in attributes ) { if (attr is AdditionalMethodInfo) { AdditionalMethodInfo m = (AdditionalMethodInfo)attr; if (m.CreationDate.Date == DateTime.Now.Date) { ctr++; } } } Console.WriteLine("Methods developed today = {0}", ctr); } } |
Die Ausgabe für das obige Beispiel wäre Methods developed today = 1, da nur eine Methode in der Klasse Test mit dem Attribut versehen wurde.
Weitere Informationen zu Attributen können hier nachgelesen werden.
Mit folgendem Code kann man das echo von sdtin aktivieren oder deaktivieren.
Besonders praktisch, da Benutzer Eingaben tätigen können, ohne das die Eingabe auf der Konsole angezeigt wird.
|
1 2 3 4 5 6 7 8 9 10 |
void setStdinEcho(bool enable = true) { struct termios tty; tcgetattr(STDIN_FILENO, &tty); if( !enable ) tty.c_lflag &= ~ECHO; else tty.c_lflag |= ECHO; (void) tcsetattr(STDIN_FILENO, TCSANOW, &tty); } |
Im folgenden zeige ich, wie man HTML Text in Textblöcken oder Labeln darstellen kann. Der Ausgangspunkt hierfür ist ein passender ValueConverter:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
public sealed class TextToHtmlConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { return value is string ? HtmlUtilities.ConvertToText(value.ToString()) : value; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } } |
Wenn man nun also einen String an einen TextBlock bindet und den ValueConverter angibt, dann wird der Inhalt automatisch durch den Converter korrekt angezeigt. Damit man den Converter verwenden kann, muss man zunächst den Namespace in der XAML anlegen.
|
1 |
xmlns:converter="using:projektname.OrdnerDesConverters" |
Anschließend muss man dann nur noch den angelegten Namespace als statische Ressource angeben.
|
1 2 3 |
<Page.Resources> <converter:TextToHtmlConverter x:Key="TXT2HTMLConv"/> </Page.Resources> |
Zuletzt kann dann das Databinding erfolgen.
|
1 |
<TextBlock Text="{Binding MyString, Converter={StaticResource TXT2HTMLConv}}"/> |
Mit folgender Funktion lässt sich ein zufälliges Passwort in C generieren. (In nächster Zeit werde ich öfters ein paar C/C++ Inhalte posten, da ich mich zur Zeit intensiv mit C beschäftige).
Zur Vorgehensweise: Es wird in jedem Schleifendurchlauf ein zufälliges Zeichen aus POSSIBLECHARS ermittelt und an die Variable retString angehangen. Die Schleife läuft so lange, bis der Zähler die vom Benutzer angegebene Anzahl erreicht hat.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #define POSSIBLECHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_*#$&%?!" char* createPassword(int count, char* fromChars) { int random, i = 0; char* retString; char temp[2]; retString = (char*)malloc(count * sizeof(char)); *retString = '\0'; srand(time(NULL)); while (i++ != count) { random = rand() % strlen(fromChars); temp[0] = fromChars[random]; temp[1] = '\0'; strcat(retString, temp); } return retString; } int main() { int length; printf("PASSWORDGENERATOR\n"); printf("Size:"); scanf("%i", &length); printf("\nPassword = %s\n", createPassword(length, POSSIBLECHARS)); system("pause"); return 1; } |
Vor ein paar Wochen bin ich auf ein interessantes Verhalten meiner Netbeans Entwicklungsumgebung gestoßen.
Ich habe eine generische Arraylist erstellt:
|
1 |
ArrayList<String> myArrayList = new ArrayList<String>(); |
Die Entwicklungsumgebung hat mir dann folgendes angezeigt:
Nach dem Ausführen des Vorschlags sah die Initialisierung der Arraylist wie folgt aus:
|
1 |
ArrayList<String> myArrayList = new ArrayList<>(); |
Der Grund der Änderung scheint offensichtlich. Beim Initialisieren von generischen Typen musste der Typparameter bisher immer doppelt angegeben werden. Seit Java 7 gibt es jetzt also die verkürzte Schreibweise; eben die Diamantinferenz (Der Name kommt tatsächlich daher, dass die generischen Klammern ‘<>‘ angeblich wie ein Diamant aussehen
).
Der Vorteil dieser Schreibweise ist lediglich die reduzierte Schreibarbeit. Bei folgendem Konstrukt ist diese Tatsache vielleicht ganz angenehm.
|
1 |
ArrayList<ArrayList<Map<String, String>>> myArrayList = new ArrayList<>(); |
In Bezug auf die Polymorphie tauchen mit der Schreibweise auch keine Probleme auf. Ausgegangen von einer Oberklasse (z.B. Animal) und einer Subklasse (z.B. Dog), wäre Folgendes so oder so nicht erlaubt:
|
1 |
ArrayList<Animal> animalList = new ArrayList<Dog>(); |
Demnach gibt es keine Missverständnisse bei der neuen Schreibweise:
|
1 |
ArrayList<Animal> animalList = new ArrayList<>(); |
Im Folgendem zeige ich, wie man WebRequests mit dem WP7 durchführen kann.
Zunächst initialisieren wir einen WebClient. Dieser wird die WebRequests für uns erledigen. Als nächstes erweitern wir das Event “OpenReadCompleted” des WebClient. Hier werden wir das Ergebnis des Requests abfangen können. Zuletzt rufen wir die Methode “OpenReadAsync()” auf, wo wir als Parameter die Uri der gewünschten Zieladresse angeben. Hier der Code dazu:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public void PerformWebRequest() { WebClient client = new WebClient(); client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted); client.OpenReadAsync(new Uri("http://google.de")); } void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { string requestResult = string.Empty; using (StreamReader s = new StreamReader((Stream)e.Result)) { requestResult = s.ReadToEnd(); } } |
Seit der Einführung von LINQ haben wir die Möglichkeit, bestehende Klassen um eigene Methoden zu erweitern. Im folgenden Beispiel zeige ich, wie wir die String Klasse um die Methode “Clear()” erweitern können.
Wir erstellen eine statische Klasse die den Namen “Extensionmethods” bekommt. In dieser Klasse wird die statische Methode “Clear()” definiert. Als Parameter übergeben wir einen String mit dem “this” Schlüsselwort davor. Dadurch legen wir fest, dass die String Klasse erweitert werden soll. Der Rückgabewert der Methode ist ein leerer String.
|
1 2 3 4 5 6 7 |
public static class Extensionmethods { public static string Clear(this string s) { return string.Empty; } } |
Wenn wir nun wie folgt einen String definieren, können wir ohne weiteres die Clear() Methode aufrufen.
Jede Klasse kann um eigene Methoden erweitert werden. Sogar die primitiven Datentypen können erweitert werden.
Mit folgender simplen Python-Klasse können Dezimalzahlen in Binärzahlen umgewandelt werden. (Ich weiß, dass Python eigene Methoden zum Konvertieren hat. Die Klasse wurde aus Eigeninteresse entwickelt.)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class DezToBinConverter(object): def __init__(self, number): self.__Number = int(number) def convertToBin(self): retString = "" while self.__Number != 0: tmp = self.__Number % 2 retString = str(tmp) + retString self.__Number = int(self.__Number / 2) return retString #Testausgabe print("DezToBin Converter") dezNumber = input("Eingabe:\n") #z.B. 5 converter = DezToBinConverter(int(dezNumber)) convertedNumber = converter.convertToBin() print(dezNumber + " Binär = " + convertedNumber) #Ausgabe -> 101 |
Mit folgendem Code kann man CSS und JS Dateien im TYPO3 Backend einbinden.
Wichtig:
Der Code funktioniert nur, wenn er nach dem Instanziieren des “doc” Objekts aufgerufen wird.
|
1 2 3 4 5 |
$this->doc = t3lib_div::makeInstance('mediumDoc'); //CSS $this->doc->getPageRenderer()->addCssFile(t3lib_extMgm::extRelPath('NameDerExtension').'res/css/my_css.css'); //JS $this->doc->getPageRenderer()->addJsFile(t3lib_extMgm::extRelPath('NameDerExtension').'res/js/my_script.js'); |