Ziemlich coole Actionskunst
Sonntag, den 22. Juni 2008by philinthecircle
Bruce Lee mit der Handkante gemalt
Jimi Hendrix mit Streichholzköpfen
by philinthecircle
Bruce Lee mit der Handkante gemalt
Jimi Hendrix mit Streichholzköpfen
Zum Abschluss des Abends stehen bei mir Bäume im Mittelpunkt. Dazu hier eine kleine Bildergeschichte (für alle Leser die Mühe mit meinen langen Texten haben…)
In diesem Artikel möchte ich euch kurz aufzeigen, was man mit System.Reflection.Emit unter C# machen kann. Dies ist bei weitem kein komplettes Tutorial sondern nur eine kleine Übersicht über die Möglichkeiten mit Emit.
Ziel ist es eine Klasse Person zu generieren die das Interface IPerson und IComparable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public interface IPerson { string Vorname { get; set; } } public class Person : IPerson, IComparable<IPerson> { private string vorName; public string Vorname { get { return vorName; } set { vorName = value; } } public int CompareTo(IPerson other) { return 1; } } |
Sicherlich macht es nicht viel Sinn in der CompareTo Methode immer 1 zurück zu geben. Ich habe es nur so gemacht, damit das Beispiel etwas einfacher zu verstehen ist. Da das Emiten von Functioncalls auf .NET Klassen etwas schwieriger ist.
Das untenstehende Codesegment zeigt wie man ein dynamisches Assembly erzeugt. Dazu definiert man zuerst einen AssemblyName und setzt auf dem AssemblyName das Property Name und Version entsprechend den Anforderungen (Zeile 2, 4, 6). Als nächstes holt man sich den AssemblyBuilder über die bestehende ApplicationDomain des Mainthreads (Zeile 9; dann läuft das Assembly unter der gleichen ApplicationDomain). Über den AssemblyBuilder ruft man die Methode DefineDynamicModule aus und erhält somit einen ModuleBuilder der für das Builden eines Modules zuständig ist (Zeile 11; ein Assembly kann mehrere Module enthalten).
1 2 3 4 5 6 7 8 9 10 11 | // Define the new AssemblyName AssemblyName assName = new AssemblyName(); // Specify the assembly name (without .dll) assName.Name = "MyEmitTest"; // Define the version assName.Version = new Version(0, 0, 0, 1); // Get the AssemblyBuilder for the current application domain AssemblyBuilder assBuilder = Thread.GetDomain().DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave); // Get the ModuleBuilder over the AssemblyBuilder ModuleBuilder modBuilder = assBuilder.DefineDynamicModule("MyFirstEmittedModule", "MyEmitTest.dll"); |
Um in dem bestehenden Module eine neue Klasse zu definieren, rufen wir die Methode DefineType des ModuleBuilders auf. Die Methode gibt ein TypeBuilder zurück, den wir brauchen um die Klasse zusammenzubauen. Damit die Klasse Person die Interfaces IPerson und IComparable
1 2 3 4 5 6 | // Define Person class which is public TypeBuilder personBuilder = modBuilder.DefineType("Person", TypeAttributes.Public); // Add IPerson interface personBuilder.AddInterfaceImplementation(typeof(IPerson)); // Add interface IComparable<IPerson> personBuilder.AddInterfaceImplementation(typeof(IComparable<>).MakeGenericType(typeof(IPerson))); |
Über den TypeBuilder personBuilder und die Methode DefineField kann ein neues Feld im Typ Person definiert werden. Dazu spezifiziert man den Namen des Feldes, den darunterliegenden Typ und den Fieldmodifier (private, protected, public) über das FieldAttribute. That’s the whole magic
1 2 | // Vorname Field FieldBuilder vornameFieldBuilder = personBuilder.DefineField("vorName", typeof(string), FieldAttributes.Private); |
Für das Definieren des Properties Vorname ist etwas mehr Arbeit nötig. Dies hat mit dem internen Aufbau der Klassen zu tun. Definiert man nämlich ein Property Vorname in C# mit einem get und set Accessor, so wird automatisch vom Compiler jeweils eine Methode get_Vorname und set_Vorname ausprogrammiert und verknüpft. Deshalb muss man nach der Definition des eigentlichen Properties über den TypeBuilder personBuilder und die Methode DefineProperty noch die Methoden get_Vorname und set_Vorname emitten. Doch Eins nach dem Anderen.
Die Methode DefineProperty des TypeBuilder personBuilder definiert den Namen des Properties (hier “Vorname”) und den Typ des Properties (hier string).
1 | PropertyBuilder vornamePropBuilder = personBuilder.DefineProperty("Vorname", PropertyAttributes.None, typeof(string), null); |
Nach der obigen Codezeile ist das Property ohne Rumpf definiert. Würde man den Typ Person bereits jetzt versuchen zur Laufzeit zu generieren, würde eine Exception geworfen, dass das Property Vorname noch nicht vollständig implementiert sei. Als erstes beginnen wir mit dem implementieren der get_Vorname Methode. Dazu ruft man auf dem TypeBuilder personBuilder die Methode DefineMethod auf und definiert die Methodenattribute (werden ver-OR-t). Da es sich bei den Methoden get_PropertyName und set_PropertyName um spezielle Methoden handelt (sogenannte Specialnames) muss das MethodAttribute SpecialName gesetzt werden!
Als nächstes holt man sich über den MethodBuilder den ILGenerator und baut über diesen die Operationen der Methode zusammen. Da dies nicht ganz trivial ist, hier ein kleiner Trick:
Der .NET Reflector von Lutze Roeder erlaubt es DLLs die mit .NET erstellt wurden einzulesen und den darunterliegenden Code zu extrahieren. Der Reflector ist erweiterbar mit einem coolen Plugin ReflectorEmitLanguage. Dieses Plugin erlaubt es den IL Code anzusehen. So kann man sich Sampleklassen mit Visual Studio bauen, diese in einer DLL speichern und schlussendlich die erzeuge DLL mit dem Reflector anzusehen. So sieht man genau wie der IL Code mit dem ILGenerator gemacht werden müsste
. Darum gehe ich jetzt nicht weiter auf den IL Code ein.
Zum Schluss muss man noch auf der Klasse mit DefineMethodOverride dem Emitter mitteilen, dass die neue Methode die Methode des Interfaces überschreibt. Sonst gibt es eine Warnung, dass die Klasse Person das Interface IPerson nicht implementiere.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Define the 'get_Vorname' method. MethodBuilder getVornameMethod = personBuilder.DefineMethod("get_Vorname", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName, typeof(string), null); // Generate IL code for 'get_Vorname' method. ILGenerator methodIL = getVornameMethod.GetILGenerator(); methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Ldfld, vornameFieldBuilder); methodIL.Emit(OpCodes.Ret); // Define the Set Method vornamePropBuilder.SetGetMethod(getVornameMethod); // Get the interface implementation MethodInfo interfaceGetVorname = typeof(IPerson).GetMethod("get_Vorname"); // Ovveride it personBuilder.DefineMethodOverride(getVornameMethod, interfaceGetVorname); |
Fast das gleiche Prinzip gilt für die Methode set_Vorname.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // Define the 'set_Vorname' method. Type[] methodArgs = { typeof(string) }; MethodBuilder setVornameMethod = personBuilder.DefineMethod("set_Vorname", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.SpecialName, typeof(void), methodArgs); // Generate IL code for 'set_Vorname' method. methodIL = setVornameMethod.GetILGenerator(); methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Ldarg_1); methodIL.Emit(OpCodes.Stfld, vornameFieldBuilder); methodIL.Emit(OpCodes.Ret); vornamePropBuilder.SetSetMethod(setVornameMethod); MethodInfo interfaceSetVorname = typeof(IPerson).GetMethod("set_Vorname"); personBuilder.DefineMethodOverride(setVornameMethod, interfaceSetVorname); |
CompareTo definiert die Methode des Interfaces IComparable
1 2 3 4 5 6 7 8 9 10 | // Make compareTo Method with the Person param Type[] compareToArgs = { typeof(IPerson) }; MethodBuilder compareToMethod = personBuilder.DefineMethod("CompareTo", MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), compareToArgs); compareToMethod.DefineParameter(1, ParameterAttributes.None, "other"); // Generate the IL code for the compareTo Method methodIL = compareToMethod.GetILGenerator(); methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Ldc_I4, 1); // Pushes the value 1 (int32) to the stack methodIL.Emit(OpCodes.Ret); |
Viel Spass
MSDN System.Reflection.Emit
MSDN System.Reflection.Emit.AssemblyBuilder
MSDN System.Reflection.Emit.MethodBuilder
.NET Reflector
.NET Reflector Add-Ins
Auf MSDN ist ein sehr interessanter Artikel über Parallel LINQ erschienen. Bei Parallel LINQ handelt es sich um eine API Erweiterung für LINQ mit dem es möglich ist, die Queries optimiert auf mehreren Prozessoren oder Cores auszuführen. Ich kann euch diesen Artikel nur wärmstens empfehlen. Gut sind auch die Punkte im Artikel wo die Autoren klar auf Probleme und Race Conditions eingehen und wie das Exceptionhandling bei mehreren Threads behandelt wird.
http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
Es gibt dann auch Webcasts zum Downloaden:
http://www.microsoft.com/germany/msdn/webcasts/serien/MSDNWCS-0806-02.mspx
Sicherlich haben schon einige von euch die Möglichkeit Services unter Windows Mobile zu erstellen vermisst. Selbstverständlich war das bis anhin schon möglich aber nur über komplizierte PInvokes. Dies hat sich nun geändert! Peter Nowak hat auf Codeplex eine Library veröffentlicht, mit der es möglich ist, Managed Services für Windows Mobile zu erstellen! Die Library ist folgendermassen aufgebaut:
Mehr dazu unter:
http://www.codeplex.com/managedserviceswm
Die technischen Details dahinter:
http://bansky.net/blog/2008/04/services-for-windows-mobile-in-managed-code/
Roshan Khan zeigt in seinem Blogartikel wie man unter Windows Mobile eine schnelle und effiziente Manipulation von Bitmaps durchführen kann. Obwohl die Klasse Bitmap sealed ist, zeigt er eine elegante Möglichkeit Bilder zu manipulieren.
http://blogs.msdn.com/windowsmobile/archive/2008/04/15/faster-c.aspx
Unbedingt bis zum Ende schauen! Dieses Video ist unglaublich eindrucksvoll , überzeugt euch selbst!
Ich habe zusammen mit meiner Freundin einen kleinen Städtetripp nach Strassburg in Frankreich (Elsass) gemacht vom 01.06.2008 bis am 05.06.2008. Ihr findet ein paar Fotos in der Hauptnavigation auf der rechten Seite unter Fotos >> Städtetripp Strassburg 2008.
Viel Spass
FXRuby ist eine Library um auf verschiedenen Plattformen mittels Ruby Applikationen mit einem grafischen Benutzerinterface zu erstellen. FXRuby basiert auf der populären opensource C++ Library FOX Toolkit.
Auf dieser Seite sieht ihr einige Möglichkeiten was man mit FXRuby alles erstellen kann:
http://www.fxruby.org/doc/examples.html
Dazu gibt es einen grossen Userguide online mit dem man direkt loslegen kann. Es muss einfach zuerst über GEMs FXRuby installiert werden!
http://www.fxruby.org/doc/book.html
Mehr zu FXRuby unter:
Ich habe heute den Film Cashback gesehen und war begeistert von den Kameraeinstellungen, den Schnitten und Übergängen im Film. Fast umgehauen hat mich aber das untenstehende Mantra der Liebe am Ende des Filmes:
”Once upon a time, I wanted to know what love was. Love is there if you want it to be. You just have to see that it’s wrapped in beauty and hidden away in between the seconds of your life. If you don’t stop for a minute, you might miss it.”
Sinngemässe Übersetzung:
"Früher wollte ich wissen was die Liebe ist. Die Liebe ist da, wenn du es willst. Du musst nur erkennen, dass Sie sich in der Schönheit und zwischen den Sekunden deines Lebens versteckt. Wenn du nicht für eine Minute anhaltest, wirst du sie vielleicht verpassen."
Unglaublich wie diese wenigen Sätze einfach alles auf den Punkt bringen! Ich denke, wenn wir das uns alle zu Herzen nehmen, wird die Welt ein viel schönerer Ort…