Training - Beratung - Projektarbeiten

www.David-Tielke.de

ConfigurationSectionDesigner jetzt auch für Visual Studio 2010

Ein weiteres Mal musste ich dieses Jahr feststellen, warum viele Leute in der Softwareentwicklung ungern auf OpenSource-Software setzen. Hat man z.B. ein OpenSource-Addin für Visual Studio in einem Projekt verwendet und bestimmte Elemente hängen von diesem Tool ab, kann imageman erst dann auf eine neuere Entwicklungsumgebung migrieren, wenn auch das entsprechende Tool für diese angeboten wird. So geschehen bei einem meiner Projekte und dem Configuration Section Designer. Jeder der schon einmal komplexere Configuration Sections implementieren musste, weiß um diese mühselige Aufgabe und so konnte ich mit dem CSD diese Arbeit in Minuten anstatt Stunden durchführen. Leider blieb mir bisher die Migration dieses Projektes auf VS 2010 verwehrt, da CSD nur für VS 2008 erhältlich war und die ehemaligen Entwickler das Projekt nicht mehr weiterführen konnten.

Seit kurzem haben neue Entwickler das CSD-Projekt übernommen und nun gibt es das Addin für Visual Studio 2010 in der Alpha-Phase, allerdings konnte ich bisher weder Bugs noch Einschränkungen feststellen.

Das Tool erlaubt die grafische Entwicklung von Configuration Sections und ist in der VS 2010-Variante nochmal um zahlreiche Features erweitert worden. Jeder der öfters an Konfigurationsdateien arbeitet, sollte sich das Tool einmal genauer anschauen!

Links
Configuration Section Designer auf Codeplex

Microsoft Springboard 2011 am 8. Juli in Köln

Neben dem Studium praxisrelevantes Wissen über neue Technologien aneignen? Ohne dabei viel Geld und Zeit zu investieren? Wenn du jetzt nickst, dann bist du hier genau richtig:

Die Microsoft Student Partner des Team West laden Dich herzlich zur IT-Konferenz Project Springboard am 8. Juli in das Microsoft Office in Köln ein!

Bei dieser studentischen IT-Konferenz mit den Schwerpunkten Software-Development und IT-Infrastruktur erwarten Dich interessante Fachvorträge zu neusten Technologien, Tipps aus der Praxis sowie einen Blick in die Microsoft Niederlassung in Köln.

Zudem hast Du die Möglichkeit, Dich mit Microsoft-Experten und –Ansprechpartnern auszutauschen und so ganz im Sinne des Networkings Deiner Karriere auf die Beine zu helfen.

Ich nehme als Student Partner ebenfalls an der Veranstaltung mit Vorträgen zu den Themen OneNote 2010 (JA! ernsthaft!) und Multithreading mit C# teil.

Die Teilnahme an dem Event ist für Studenten natürlich kostenlos.

Wir freuen uns auf einen tollen Tag mit Dir!

(Selbstverständlich sind nicht nur Studenten sondern alle Interessierten herzlich eingeladen, die Teilnahme ist für alle kostenlos).“

Anmeldung: http://www.stnc.de/?page_id=16&event_id=28

Vorträge/Referenten: http://www.stnc.de/?page_id=114

Wie funktioniert LINQ? - Teil 1: IEnumerable<T>, IEnumerator<T> und yield

Wenn man die Arbeitsweise von LINQ verstehen möchte, kommt man nicht darum herum, sich mit den Interfaces IEnumerable<T> und IEnumerator<T> zu beschäftigen. Beide gibt es bereits seit .NET 2.0 und werden seit jeh her genutzt, um aus einer Datensammlung alle Elemente der Reihe nach zu bearbeiten. Im ersten Beitrag zur Serie "Wie funktioniert LINQ?", schauen wir uns diese beiden Interfaces einmal genauer an.

Wie enumeriert man eine Klasse?

Beim Enumerieren wird eine Datensammlung Element für Element durchlaufen.Da die Elemente einzeln nacheinander abgefragt werden, muss an einer Stelle gespeichert werden, welches das letzte Element war, das durchlaufen wurde. Solch einen Status wird normalerweise von einem Zustandsautomaten (eng. Statemachine) festgehalten. Die Implementierung ist relativ aufwändig, wir schauen uns das mal an einer einfachen Klasse an:

class Collection<T>
{
	private T[] _data;
	private int _current;

	public Collection(int capacity)
	{
		_data = new T[capacity];
		_current = -1;
	}

	public T this[int index]
	{
		get { return _data[index]; }
		set { _data[index] = value; }
	}

	public T Current
	{
		get
		{
			return _data[_current];
		}
	}

	public bool MoveNext()
	{
		if (_current >= _data.Length-1)
		{
			return false;
		}
		else
		{
			_current++;
			return true;
		}
	}
}
Listing 1: Eine enumerierbare Collection-Klasse mit gemerktem Zustand
Die Klasse hat intern ein Array vom Typ T um Daten zu speichern (Zeile 3) und das Feld _current (Zeile 3) um das zuletzt zurückgegebene Element zu "merken". Beim Aufruf von der Methode MoveNext() wird der interne Merker auf das nächste Element gesetzt (sofern vorhanden) und true oder false zurückgegeben, je nachdem ob ein weiteres Element vorhanden war, oder nicht. Damit wir später einfacher mit einer while-Schleife über die Collection enumerieren können, startet _current bei -1. Beim Aufruf der Eigenschaft Current wird das Element zurückgegeben, das gerade an der Reihe ist, also auf das unser Merker "zeigt".
Mit dieser Klasse können wir nun mit einer while-Schleife die einzelnen Elemente der Reihe nach ausgeben.
Collection<int> numbers = new Collection<int>(3);
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;

while (numbers.MoveNext())
{
   Console.WriteLine(numbers.Current);
}
Listing 2: Das Enumerieren der Klasse mit einer while-Schleife
Unsere erste Überlegung war richtig, wir können über die Collection enumerieren. Aber wir sind noch nicht fertig, was passiert wenn wir auf unterschiedliche Arten über die Collection iterieren möchten? Stellen Sie sich vor, in Thread A geben wir die Elemente 1,2 aus, möchten dann mit Thread B die Elemente 1,2,3 und am Ende mit Thread A noch Element 3 ausgeben. Mit unserer derzeitigen Lösung funktioniert das nicht auf einem gemeinsamen Collection-Objekt, da der Status unsere Enumeration pro Klasse gespeichert wird. Um dieses Problem zu umgehen, erzeugen wir eine Iterator-Klasse.
class Collection<T>
{
	private T[] _data;

	public Collection(int capacity)
	{
		_data = new T[capacity];
	}

	public T this[int index]
	{
		get { return _data[index]; }
		set { _data[index] = value; }
	}

	public Iterator<T> GetIterator()
	{
		return new Iterator<T>(this);
	}
	
	public class Iterator<T>
	{
		private Collection<T> _collection;
		private int _current;

		public Iterator(Collection<T> collection)
		{
			_collection = collection;
			_current = -1;
		}

		public T Current
		{
			get
			{
				return _collection._data[_current];
			}
		}

		public bool MoveNext()
		{
			if (_current >= _collection._data.Length - 1)
			{
				return false;
			}
			else
			{
				_current++;
				return true;
			}
		}
	}
}
Listing 3: Eine enumerierbare Collection-Klasse mit einer nested Iterator-Klasse.

Die Iterator-Klasse ist nested deklariert und übernimmt jetzt die Funktion der Statemachine und bietet die Methode MoveNext und die Eigenschaft Current an. Um eine Iterator-Instanz zu bekommen, ruft man auf das Collection-Objekt die GetIterator() - Methode auf. Dadurch ist gewährleistet, das nun unabhängig über diese Collection enumeriert werden kann:

Collection<int> numbers = new Collection<int>(3);
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;

var it1 = numbers.GetIterator();
var it2 = numbers.GetIterator();

it1.MoveNext();
it2.MoveNext();

Console.WriteLine(it1.Current);
Console.WriteLine(it2.Current);
Listing 4: Mit der Iterator-Klasse kann nun unabhängig enumiert werden.

An diesem einfachen Beispiel kann man bereits erkennen das die Implementierung einer enumerierbaren Klasse keine einfache Aufgabe ist und viel zusätzlicher Code nötig ist. Später schauen wir uns noch ein C#-Konzept an, um das alles vom Kompiler erzeugen zu lassen.

Enumierierbar mit IEnumerable<T>

In unserem Beispiel hat die Klasse Collection die GetIterator()-Methode, um die Referenz auf ein Objekt zu bekomme, mit dem ich über die Collection enumerieren kann. Würde man dieses Muster in anderen Klassen so implementieren, könnte man sagen, das alle Klassen welche die Methode GetIterator() anieten, sind enumerierbar. Dann könnte ich diese "Fähigkeit" theoretisch auch durch ein Interface deutlich machen, oder? Genau das macht das Interface IEnumerable<T>, welches im .NET-Framework bereits implementiert ist. In diesem Interface ist nur eine Methode GetEnumerator() deklariert (Gleiche Idee wie GetIterator() aus dem Beispiel), die dem Aufrufer einen Enumerator zurückgibt, mit dem über diese Elemente enumeriert werden kann.

public interface IEnumerable<out T> : IEnumerable
{
     IEnumerator<T> GetEnumerator();
}
Listing 5: Das Interface IEnumerable<T>
Dieses Interface wird von allen gängigen Collections wie List, Dictionary usw. implementiert, das heßt also, alle diese Klassen sind enumerierbar. Darüber hinaus gibt es auch noch eine nicht generische Variante des Interfaces, allerdings spielt das für unsere Betrachtungen keine Rolle.

Enumerieren mit IEnumerator<T>

Wenn man auf ein Objekt einer Klasse, welches das Interface IEnumerable<T> implementiert, die GetEnumerator()-Metode aufruft, bekommt man ein Enumerator-Objekt zurückgeliefert. Dieses Objekt nutzt das selbe Konzept wie die Iterator-Klasse aus unserem Beispiel, implementiert allerdings zusätzlich das Interface IEnumerator<T>.

public interface IEnumerator
{
	object Current { get; }
	bool MoveNext();
	void Reset();
}

public interface IEnumerator<out T> : IDisposable, IEnumerator
{
	T Current { get; }
}
Listing 6: Die Interfaces IEnumerator<T> und IEnumerator

Das Interface leitet von IEnumerator ab und so verpflichten sich Klassen, die IEnumerable<T> implementieren, die Methoden MoveNext(), Reset() und die Eigenschaft Current zu implementieren. Auch das entspricht unserer Strategie aus dem Beispiel.

Enumerierbarkeit im .NET-Framework

Um enumerierbare Klassen im .NET-Framework zu nutzen, gibt es zahlreiche Methoden und Sprachkonstrukte, wie z.B: die foreach-Schleife. Damit enumerierbare Klassen eine gemeinsame Schnittstelle haben, wurden die Interfaces IEnumerable<T> und IEnumerator<T> eingeführt. Um das Ganze zu verdeutlichen, schauen wir uns die Metadaten der Klasse List<T> an (unwichtige Bereiche wurden entfernt):

public class List<T> : IEnumerable<T>, IEnumerable
{
	public List<T>.Enumerator GetEnumerator();

	public struct Enumerator : IEnumerator<T>, IEnumerator
	{
		public T Current { get; }
		public bool MoveNext();
	}
}
Listing 7: Die Metdaten der Klasse List<T>

Analog zu unsem Beispiel wurde von den Entwicklern des .NET-Frameworks das Interface IEnumerable<T> implementiert, um eine gemeinsame Schnittstelle für das Erzeugen eines Enumerators zu haben. Weiterhin wurde eine nested Struktur definiert (bei uns war es eine Klasse), um einen Unabhängigen Enumerator zu erzeugen.