ASP / ASP.NET MVP 2010
Dienstag, 19. Januar 2010 20:23
Anfang Jahr erhielt ich eine Email von Microsoft, das ich für das Jahr 2010 renominiert wurde :)
Das freut mich ungemein und ich möchte mich bei den Betreibern und Moderatoren von ASP.NET Zone und myCSharp bedanken.
Diese Auszeichnung durfte ich jetzt schon das vierte Mal in Folge entgegennehmen, wobei 4 meine Lieblingszahl ist :)
Sicherlich finde ich die Zeit auch mal in Konstanz beim .NET Stammtisch Konstanz / Kreuzlingen vorbeizuschauen und einen Vortrag zu halten.
Auf ein erfolgreiches Jahr 2010!
Tags:
ASP.NET, MVP, Microsoft, Neuigkeiten
this oder kein this
Freitag, 1. Januar 2010 09:37
Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen.
Bisher sind in dieser Reihe folgende Kommentare erschienen:
Heute, am 1. Januar 2010, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:
this oder kein this
So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema.
Generell ist es sinnvoll, wenn ohne weiteres Zutun gleich erfasst werden kann, ob es sich um eine lokale, statische oder instanzbehaftete Variable handelt.
Aus diesem Grund gibt es Konventionen, wie etwas auszusehen hat, sei dies mit Pascal- (fooBar) / Camel-Casing (FooBar) oder durch Prä- / Postfixe (m_foo, foo_m).
Im Allgemeinen hat es sich bei mir so entwickelt, dass ich mich immer mehr zu der empfohlenen Microsoft Konvention hin bewegt habe, was die Einarbeitung in andere Projeke um einiges leichter macht,
da diese Konvention häufig – wenn auch teilweise abgeändert – verwendet wird.
Im aktuellen Streitgespräch geht es darum, ob this verwendet wird / nicht verwendet wird und wo es verwendet wird.
this wird zwanghaft benötigt, um auf die Referenz auf sich selber, in die Hand zu bekommen.
Beispielsweise wenn in einer User-Klasse eine .Save-Methode angeboten wird, die ihrerseits aber einen Service benutzt um sich speichern zu lassen:
public class User
{
public void Save()
{
ServiceLocator
.Resolve<IUserService>()
.Save(this);
}
}
Erweiterungsmethoden benutzen this als Kennzeichnung:
static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
{
action(item);
}
}
Bei einer Indexerdeklaration wird this auch benötigt:
public User this[sring index]
{
get { return this._list[index]; }
set { this._list[index] = value; }
}
Ein andere Stelle wo this benutzt werden muss, ist beim angeben von zusätzlichen Konstruktoren von sich selbst, die auch noch aufgerufen werden sollen:
public class UserService
{
private readonly IRepository<User> _userRepository;
public UserService() : this(new XmlUserRepository())
{
}
public UserService(IRepository<User> userRepository)
{
_userRepository = userRepository;
}
}
Im ersten Konstruktor wird angegeben, das auch der zweite Konstruktor mit einem Parameter aufgerufen werden soll.
Wenn die Instanzvariable “_userRepository” keinen Unterstrich hätte – also “userRepository” – müsste this verwendet werden, damit der Kompiler zwischen Instanzvariable und Argument unterscheiden kann, also:
private readonly IRepository<User> userRepository;
public UserService(IRepository<User> userRepository)
{
this.userRepository = userRepository;
}
Zu Anfang habe ich das Präfix “_” vor einer Instanzvariable benutzt, so kann man – auch im Intellisense – ohne Probleme auswählen und unterscheiden, da alle schön gruppiert sind.
In Visual Studio 2005 gab es allerdings kein Intellisense bei der Eingabe von “_test” im Code-Editor.
Ich habe dort “this._test” genutzt, denn es ist ja ein Instanzmember und mit der Eingabe von “this.” gab es dann Intellisense.
Ab Visual Studio 2008 gibt es bereits bei der Eingabe von “_” Intellisense, somit wäre “this” überflüssig. Allerdings habe ich mir angewöhnt, this überall anzugeben, wo sich etwas auf die Instanz bezieht.
Also für Methodenaufrufe auf der Instanz (in der Regel protected oder private Methoden), Eigenschaften sowie Instanzfelder.
Es ist so möglich auf den ersten Blick zu unterscheiden und erfassen, was eine lokale Variable ist, was ein statisches Feld / Konstante. Oder doch eine Instanzvariable?.
Was meint ihr dazu?
Tags:
C#, Streitgespräch, this
InternalsVisibleToAttribute und signierte Assemblies: So funktionierts garantiert.
Freitag, 4. Dezember 2009 16:46
Stellt euch vor, ihr habt zwei Assemblies:
- MyProject.Core
- MyProject.Core.Tests
Im Core-Projekt gibt es Typen, die nicht öffentlich gemacht werden sollten, allerdings für die UnitTests zugänglich sein sollen.
Nun, das ist ein kleines Problem, wenn man das Attribut “InternalsVisibleTo” kennt, mithilfe folgender Dekleration in der AssemblyInfo.cs des MyProject.Core-Projekts kann dies einfach erledigt werden:
[assembly: InternalsVisibleTo("MyProject.Core.Tests”)]
Das macht sogar sehr viel Sinn, denn sonst können Kollisionen und Verwechslungen der Extensionmethods beim Endbenutzer vorkommen.
Soweit, so gut. Die Typen der MyProject.Core-Assembly sind jetzt in der MyProject.Core.Tests-Assembly sichtbar.
Müssen die Projekte jedoch signiert sein, kommt es zu einem grösseren Problem.
In mehreren Blogs sind die nötigen Schritte beschrieben, jedoch werden da wichtige Punkte nicht genannt, die einem zur Verzweiflung treiben können.
Die sind wie folgt:
- Alle involvierten Assemblies müssen signiert werden.
- Der PublicKey muss vom Projekt bezogen werden, bei dem die Internals sichtbar werden sollen, in unserem Fall also das MyProject.Core.Tests-Projekt.
Nach einer weiteren Suche bin ich schlussendlich auf einem (selbsternannten) Newbie-Blog fündig geworden.
Noch später sties ich dann auf die folgende Anleitung, die eigentlich alles beinhaltet, sodass ich nicht alles im Detail niederschreiben muss, trotzdem die wichtigen Punkte nennen kann und vorallem die Lösung wieder einmal finde:
Also, beachtet die oben stehenden zwei Punkte und haltet euch an folgende Anleitung:
Tags:
Tipps, .NET, Assembly, InternalsVisibleTo, StrongName
Reflection – Fluch oder Segen?
Dienstag, 1. Dezember 2009 09:37
Am 13. Oktober 2008 haben Golo Roden und ich unter dem Titel Noch Fragen, Roden? Ja, Bucher! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen.
Bisher sind in dieser Reihe folgende Kommentare erschienen:
Heute, am 1. Dezember 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:
Reflection – Fluch oder Segen?
So wohl Golo wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Golos Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:
Reflection?
Reflection, Reflexion bzw. Introspektion macht es möglich, Programme wie Daten zu behandeln und so Informationen über Typen / Member abzurufen und auch zu setzen.
Eine Einführung zu Reflection findet sich bspw. hier, und auf myCSharp.de findet sich ein super ausführlicher und tiefgehender Artikel, der auf jeden Fall lesenswert ist.
Darüber hinaus ist es per Reflection möglich, eine späte Bindung in jeglicher Hinsicht zu erreichen. Sei dies das dynamische Laden einer Assembly oder auch das dynamische Aufrufen einer Methode zur Laufzeit.
Damit lassen sich Service Locator und Dependency Injection Container - also Systeme zur Entkoppelung - umsetzen, die je nach Konfiguration eine andere Assembly mitsamt ihren Typen lädt.
Ein praktischer Anwendungsfall wäre ein Serialisierungsmechanismus, der Objekthierarchien bspw. in XML-Form abspeichern kann.
Mithilfe von Reflection können die zu speichernden Typen in Form einer Instanz von System.Reflection.Type abgefragt werden.
Ein Type Objekt macht alles verfügbar, was zu einem Typen gehört, seien dies Methoden, Attribute, Eigenschaften oder gar Felder.
Kleines Beispiel:
int count = 2012;
Type typeOfCount = count.GetType(); // Oder: typeof(int)
Console.WriteLine(typeOfCount);
Ausgabe ist die Stringrepräsentation des Types der mit dem Alias int verknüpft ist, also: “System.Int32”.
Schluss ist damit noch lange nicht, es ist genau so möglich Code zur Kompile- oder Laufzeit dynamisch zu erstellen.
Das .NET Framework bietet die hierzu nötigen Klassen im Namensraum System.Reflection.Emit bereit.
Die Anwendung dieser API ist jedoch relativ umständlich und komplex, dafür extrem mächtig.
Segen?
Reflection und Bibliotheken die darauf aufbauen birgen ein riesen Potential und ungeahnte Möglichkeiten.
Die Anwendung ist extrem einfach und viele Features im .NET Framework selber bauen auch auf Reflection auf.
Also auf jeden Fall ein Segen… auf der einen Seite.
Fluch?
Auf der anderen Seite kann es auch zu einem Fluch werden, denn mit Reflection kann viel Humbug getrieben werden.
Zum einen ist die Ausführung von Code der Reflection nutzt, um einiges langsamer, was zu Performanceproblemen führen kann, zum anderen kann so auch die Mauer der Zugriffsmodifizierer umgangen werden, da es ohne viel Aufwand möglich ist, auch private Members einer Klasse auszulesen.
Zudem können Probleme auftreten, wenn die Umgebung in der eine Anwendung läuft, zuwenig Rechte hat. Das kann dazu führen, das eine Anwendung überhaupt nicht, oder nur eingeschränkt lauffähig ist, in restriktiven Umgebungen.
Über das dynamische Laden von Assemblies kann es zu Sicherheitsproblemen kommen, falls die geladenen Assemblies schädlichen Code enthalten.
Allerdings lassen sich viele der geschilderten Probleme umgehen bzw. beheben.
Caching – dafür gibt es auch schon diverse, fertige APIs, die auch neben Caching noch weitere Verbesserungen für Reflection bringen.
Alle anderen Probleme brauchen eine vorsichtige und sparsame Verwendung von Reflection.
Mein Credo dabei ist: So viel wie nötig, so wenig wie möglich. Denn sehr vieles geht auch ohne Reflection, kann aber mit Reflection nachgebaut werden.
System.Linq.Expressions
Mit der Einführung von LINQ und in dessen Zuge auch dem neuen Namensraum System.Linq.Expressions gibt es eine weitere und einfachere Möglichkeit, Code dynamisch zu generieren und vorallem auch zu analysieren.
Zum einen ist es mit LINQ und den Expression Trees möglich, Lambda Ausdrücke, die in eine Methode eingespiesen werden, auseinander zu nehmen und zu analysieren.
In .NET selber wird das bspw. verwendet, um LINQ abfragen zu parsen und diese anschliessend in ein SQL-Statement zu überführen.
Zumindest laut meinem Wissen, ist es mit dem Expressions-API nur möglich, Methoden dynamisch zu generieren und zu kompilieren. Das ist eine Einschränkung, die allerdings für viele Anwendungsfälle nicht weiter tragisch ist, damit lässt einfach schon relativ viel realisieren.
Das Expressions-API nutzt intern auch Reflection und schlussendlich auch die Klassen aus dem Namensraum System.Reflection.Emit.
Beispiele mit dem Expressions-API:
Addieren von zwei Zahlen per statischem Code.
private void AddPlain()
{
int one = 1;
int two = 2;
int result = one + two;
}
Addieren von zwei Zahlen, die Methode wird dynamisch zusammengebaut.
private static void AddWithExpressions()
{
ConstantExpression numberOneExpression = Expression.Constant(2);
ConstantExpression numberTwoExpression = Expression.Constant(3);
BinaryExpression addExpression = Expression.Add(numberOneExpression, numberTwoExpression);
var lambdaExpression = Expression.Lambda<Func<int>>(addExpression);
Func<int> methodDelegate = lambdaExpression.Compile();
int result = methodDelegate();
}
Funktion zum Addieren von zwei Zahlen per statischm Code.
private static int AddFunctionPlain(int left, int right)
{
return left + right;
}
Funktion zum Addieren von zwei Zahlen dynamische generiert.
private static Func<int, int, int> GenerateAddFunction()
{
ParameterExpression leftParameter = Expression.Parameter(typeof(int), "left");
ParameterExpression rightParameter = Expression.Parameter(typeof(int), "right");
BinaryExpression addExpression = Expression.Add(leftParameter, rightParameter);
var lambdaExpression = Expression.Lambda<Func<int, int, int>>(addExpression, leftParameter, rightParameter);
Func<int, int, int> methodDelegate = lambdaExpression.Compile();
return methodDelegate;
}
Wie man sehen kann, ist die Nutzung von Expressions zum dynamische Generieren von Methoden für Ihre Mächtigkeit immer noch relativ einfach zu nutzen.
Fazit
Das war ein kurzer Rundflug durch Reflection und verwandte Gebiete, in dem ich versucht habe, die Vorteile, Möglichkeiten sowie auch Gefahren aufzuzeigen.
Reflection ist genial, aber nur wenn es sinngemäss und mit Vorsicht eingesetzt wird.
Also: Fluch und Segen :)
Tags:
.NET, Streitgespräch, Type, Lambda, LINQ, Expressions, Reflection, Reflexion