Das.NET Framework ist eine neue Programmierplattform, die Microsoft nach mehrjähriger Entwicklung im Januar 2002 in der Version 1.0 freigegeben hat und von der es mittlerweile zahlreiche Versionen gibt. Eine ausführlichere Darstellung des.NET Frameworks finden Sie in dem Buch .NET Crashkurs.

Das.NET Framework sollte nicht mit der.NET-Strategie insgesamt gleichgesetzt werden. Das Framework ist ein Baustein der.NET-Strategie. Andere Bausteine wie die.NET Enterprise Server basieren (noch) nicht auf dem.NET Framework.

Geschichte

Die Entwicklung des.NET Framework begann aus der Entwicklung einer neuen Version des Component Object Models (COM). Sehr schnell stellte sich heraus, dass.NET sich so weit von COM entfernen würde, dass ein neuer Name gerechtfertigt ist. Zunächst wurde das Konzept "Next Generation Windows Service" (NGWS) genannt, seit Juli 2000 verwendet Microsoft den Begriff.NET Framework.

Installation

Das.NET Framework ist ein kostenloses Add-on für folgende Betriebssystem: Windows 98, Windows ME, Windows NT 4.0, Windows 2000 und Windows XP. Ab dem Windows Server 2003 gehört das.NET Framework zum Standardinstallationsumfang. Das.NET Framework Redistributable ist ein 22 MB großes Setup. Für Windows CE.NET gibt es eine Light-Version, das sogenannte.NET Compact Framework.

Werkzeuge

Das Framework Redistributable enthält Kommandozeilencompiler für die Sprachen Visual Basic.NET, C# und JScript.NET, sodass dies als Grundpaket für die Entwicklung von.NET-Anwendungen bereits ausreicht.

Daneben gibt es ebenfalls kostenlos ein 134 MB (englische Version) bzw. 151 MB (deutsche Version) großes Software Development Kit (SDK) mit Werkzeugen, Dokumentation und Beispielen. Speziell für die Entwicklung von Anwendungen für Handheld-Computer, Smartphones und WAP-Handys gibt es das Mobile Internet Toolkit (MIT). Nicht kostenlos ist die integrierte Entwicklungsumgebung Visual Studio.NET, die es in drei verschiedenen Versionen gibt (siehe Grafik).

Abbildung 1: Funktionsumfang der verschiedenen Werkzeugpakete.

Zwischensprache

Das.NET Framework arbeitet – genau wie die Programmiersprache Java – mit einer Zwischensprache. Ein Compiler einer.NET-Sprache erzeugt also nicht einen prozessorspezifischen Maschinencode, sondern einen plattformunabhängigen Zwischencode. Dieser Zwischencode heißt Microsoft Intermediate Language (MSIL) und bildet eine so genannte Assembly.

Erst zur Laufzeit wird dieser MSIL-Code dann in einen prozessorspezifischen Maschinencode (Native Code) umgewandelt. MSIL-Code wird aber nicht interpretiert, sondern von einem sogenannten Just-in-Time-Compiler Stückchenweise umgewandelt und dann ausgeführt. Dabei berücksichtigt der Just-in-Time-Compiler prozessorspezifische Optimierungsmöglichkeiten. Dadurch, dass nicht interpretiert, sondern vor der Ausführung kompiliert wird und der Just-in-Time-Compiler sehr schnell ist, ist der Performance-Verlust durch die Intermediation sehr gering. Im Zweifel gibt es auch die Möglichkeit, die das Ergebnis der Kompilierung von MSIL zu Maschinencode zu speichern und später auszuführen. Dies nennt man ein Native Image. Ein Native Image ist aber nicht mehr plattformunabhängig.

Die Compiler der Sprachen Visual Basic.NET, J#, C# und JScript.NET erzeugen immer MSIL-Code. Visual C++ 7.0 erzeugen wahlweise MSIL-Code oder direkt Native Code.

Abbildung 2:
Intermediation-Konzept im.NET Framework

Einheitliche Laufzeitumgebung

Die Ausführung einer.NET-Anwendung setzt eine Laufzeitumgebung voraus, die Common Language Runtime (CLR) genannt wird. Die CLR stellt den Just-in-Time-Compiler und zahlreiche andere Basisdienste bereit, die von allen.NET-fähigen Sprachen verwendet werden. Dazu gehört zum Beispiel ein Garbage Collector, Exception Handling, ein Sicherheitssystem und die Interoperabilität mit nicht.NET-Anwendungen.

Abbildung 3:
Die CLR als einheitliche Laufzeitumgebung

Programmcode, der im Rahmen der CLR ausgeführt wird, heißt Managed Code (verwalteter Code). Der restliche Code wird entsprechend Unmanaged Code (nicht-verwalteter Code) genannt.

Die CLR löst das Problem, dass bisher jede Sprache seine eigene Laufzeitumgebung benötigt hat und diese Laufzeitumgebungen sehr unterschiedliche Dienste bereitgestellt haben, was deutliche Unterschiede in der Programmierweise und im Programmierkomfort mit sich gebracht hat.

Wenn eine.NET-Anwendung gestartet wird, ruft Windows nicht die CLR selbst direkt auf, sondern zunächst einen sogenannten Runtime Host. Dieser lädt die CLR und übergibt der CLR den Einsprungpunkt für die Anwendung. Es gibt derzeit drei Runtime Hosts: den Shell Runtime Host, den Internet Explorer Runtime Host und ASP.NET. In Zukunft werden auch andere Office- und BackOffice-Anwendungen als Host fungieren können.

Abbildung 4:
Anwendungstypen und Runtime Hosts

Sprachintegration

Das.NET Framework ermöglicht die Zusammenarbeit der unterschiedlichsten Sprachen. Zusammenarbeit bedeutet dabei nicht nur, dass ein Aufruf von einem Programmcode möglich ist, der in einer anderen Sprache geschrieben wurde, sondern auch das in objektorientierten Sprachen eine Vererbung von Klassen möglich ist, die in einer anderen objektorientierten Sprache entwickelt wurden.

Basis für diese Sprachintegration ist einerseits die Zwischensprache MSIL und die CLR und andererseits die so genannte Common Language Specification (CLS). Die CLS ist ein Regelwerk für Compiler, das festlegt, wie die Umsetzung von sprachspezifischen Konzepten in die MSIL erfolgen muss. Kern der CLS ist das CommonType System (CTS), das ein einheitliches System von Datentypen definiert. Denn nur wenn die verschiedenen Sprachen die gleichen Datentypen verwenden, ist eine problemlose Integration möglich.

Einheitliche Klassenbibliothek

Ein weiterer Aspekt, der die Programmierung in verschiedenen Programmiersprachen bislang höchst unterschiedlich gemacht hat, waren die verschiedenen Funktions- bzw. Klassenbibliotheken. Die.NET Framework Class Library (FCL) ist eine sehr umfangreiche Klassenbibliothek, die von allen.NET-Sprachen aus genutzt werden kann. Selbst wenn es in verschiedenen.NET-Sprachen noch alternative Möglichkeiten für die Ausführung verschiedener Systemfunktionen (z.B. den Dateisystemzugriff) gibt, sollten die Klassen der FCL genutzt werden. Dies vermindert den Lern- und Umstellungsaufwand beim Wechsel auf eine andere Sprache enorm. Die FCL ist implementiert als eine Reihe von DLLs (Managed Code).

Die FCL enthält in der Version 1.0 genau 2246 öffentliche Klassen (Umfang des.NET Framework Redistributable, optionale Add-ons nicht eingerechnet). Um die Übersichtlichkeit zu gewährleisten, sind die FCL-Klassen in Namensräume eingeteilt. Ein Beispiel für einen FCL-Klassennamen ist System.Web.UI.Control.

 

In ì Kapitel 7 erfahren Sie mehr über die Möglichkeiten der FCL.

 

Code-Sicherheit

Der Schutz vor schädlichen Codes ist ein immer wichtigeres Thema. Die CLR bietet daher ein neues Sicherheitssystem, das nicht mehr nur die Rechte des Benutzerkontos, unter dem der Code ausgeführt wird, berücksichtigt, sondern auch die Herkunft des Programmcodes. Das Sicherheitskonzept wird Code Access Security (CAS) genannt und ist die Weiterentwicklung des Zonenkonzepts des Internet Explorers, des Microsoft Authenticode-Verfahrens zur digitalen Signierung von Programmcode und der Software Restriction Policy (SRP) unter Windows XP.

Die CLR ermittelt zur Bestimmung der Ausführungsrechte von Managed Code zunächst die Beweislage (engl. evidence). Zur Beweislage gehören insbesondere der Autor des Codes (hinterlegt durch das Authenticode-Verfahren) und der Speicherort des Codes (Zonenkonzept). Auf dieser Basis werden die Rechte des Codes ggf. eingeschränkt. Selbstverständlich erhält der Code niemals mehr Rechte als der Benutzer, unter dem der Code läuft, denn das Windows-Sicherheitssystem wirkt nach wie vor zusätzlich.

Die CAS kann durch die Definition von Code-Gruppen und Berechtigungssätzen sehr fein konfiguriert werden.

Abbildung 5:
Mischung aus Code-Berechtigungen und Benutzerberechtigungen in der.NET Framework Code Access Security

Komponentenkonzept

Das.NET Framework ist nicht nur objektorientiert, sondern auch komponentenorientiert. Im Mittelpunkt des Komponentenkonzepts stehen die sogenannten Assemblies. Es gibt Assemblies in Form einer EXE oder einer DLL.

Eine DLL-Assembly ist immer eine wieder verwendbare Softwarekomponente, die von einer anderen Assembly genutzt werden kann. Nur eine EXE-Assembly lässt sich als eine unabhängige Anwendung starten. Auch eine EXE-Assembly kann aber Dienste für Andere bereitstellen. Dieses Konzept unterscheidet sich zunächst nicht von dem Komponentenkonzept unter dem Component Object Modell (COM).

Eine Assembly ist ein Verbund aus einer oder mehreren MSIL-Datei, wobei mindestens eine der Dateien eine DLL oder EXE ist. Optional können auch nicht-MSIL-Dateien, so genannte Ressource-Dateien (z.B. Datenbank-, Grafik- oder Sound-Dateien), Teil der Assembly sein. Welche Dateien zum Verbund gehören, wird durch ein Manifest bestimmt. Vor der Ausführung vom Code aus einer Assembly wird durch die CLR geprüft, ob alle benötigten Dateien in der gewünschten Version vorhanden sind. Das Manifest ist Teil der DLL oder EXE.

Die folgende Grafik zeigt den Aufbau einer Assembly mit mehreren Dateien. Die MSIL-Dateien verwendet als Dateiformat das Portable Executable-Format (PE). Der CLR Header enthält Unmanaged Code zum Laden des Runtime Hosts. MSIL-Dateien, die kein Manifest enthalten, werden Modul genannt. Ressourcen können auch in PE-Dateien eingebettet sein.

Abbildung 6:
Aufbau einer Assembly

Auch in COM ab Windows XP gibt es Assemblies und Manifeste mit ähnlicher Bedeutung. Dort ist eine Assembly ein Verbund aus mehreren COM-Komponenten zwecks Vermeidung der DLL-Hölle.

Meta-Daten

Jede Assembly und damit auch jeder.NET-Komponente ist komplett selbstbeschreibend, d.h. es sind ausführliche Informationen über die in der Komponente enthaltenen Klassen und deren Mitglieder enthalten. Diese Meta-Daten sind Pflicht. Dies ist ein großer Fortschritt gegenüber COM, wo die Selbstbeschreibung in Form von Typbibliotheken eine oft vernachlässigte Option war.

Das Auslesen der Meta-Daten einer.NET-Komponente nennt man Reflection. Reflection ist integraler Bestandteil des.NET Frameworks, auf dem vier wichtige Mechanismen beruhen:

¨     Beim Bindungsmechanismus ermittelt die CLR mittels Reflection den aufzurufenden Programmcode

¨     Die in.NET eingebauten Mechanismen zur Objektserialisierung benötigen die Meta-Daten, die sie via Reflection ermitteln. Objektserialisierung ist wiederum die Basis für das Remoting in.NET.

¨     Der Garbage Collector verwendet Reflection um festzustellen, welche Objekte noch in Benutzung sind.

¨     Mittels des Reflection-Mechanismus kann man dynamisch Code zur Laufzeit erzeugen.

XCOPY-Deployment und Versionierung 

Die meisten.NET-Anwendungen müssen nicht mehr installiert werden, sondern können einfach an einen beliebigen Ort kopiert und von dort gestartet werden (Der Begriff XCOPY-Deployment nimmt Bezug darauf, dass zum Installieren einer.NET-Anwendungen der DOS-Befehl XCOPY ausreicht).

Diese Rückbesinnung auf die Wurzeln von Windows ist möglich durch den Verzicht auf die Registry als Konfigurationsspeicher und der Speicherung von DLLs im /System32-Verzeichnis (oder anderen zentralen Verzeichnissen). Anwendungsspezifische Konfigurationsinformationen werden nun in Form von XML-Dateien im Anwendungsverzeichnis abgelegt. Auch alle benötigten DLLs sollten dort liegen. Nur für wenige Ausnahmen, in denen eine Mehrfachnutzung einer DLL sinnvoll ist (z.B. bei der Framework Class Library), gibt es weiterhin einen zentralen Speicherort, den sogenannten Global Assembly Cache (GAC), der unter %Windows%/Assembly liegt. Der GAC ist aber kein einfaches flaches Verzeichnis, sondern eine komplexe Verzeichnishierarchie, die ermöglicht, gleichnamige DLLs in beliebig vielen verschiedenen Versionen zu speichern. Dies ist das Ende der DLL-Hölle (der gegenseitigen Störung von Anwendungen durch die Verwendung einer DLL in unterschiedlichen, inkompatiblen Versionen).

Abbildung 7:
Ansicht des GAC mit der itvisions.dll in drei versc hiedenen Versionen

Plattformunabhängigkeit

Das.NET Framework ist nicht nur durch die Verwendung der Zwischensprache MSIL plattformunabhängig. Microsoft hat weite Teile des.NET Framework standardisieren lassen bei der European Computer Manufacturers Association (ECMA). Der Standard heißt Common Language Infrastructure (CLI), ECMA-Standard Nr. 335.

Zum Zeitpunkt der Erstellung dieses Buchs gibt es eine Implementierung der CLI für FreeBSD. Weitere  Implementierungen für LINUX und für verschiedene UNIX-Derivate sind in Arbeit.

Im Rahmen der Standardisierung hat Microsoft auch weite Teile des Quellcodes des.NET Frameworks und der Programmiersprache C# für jedermann zugänglich gemacht (Shared Source CLI).

Von der Standardisierung ausgenommen sind allerdings die Datenbankschnittstelle ADO.NET (FCL-Namespace System.Data) und die Benutzeroberflächen-Bibliotheken Windows Forms (FCL-Namespace System.Windows.Forms) und ASP.NET (FCL-Namespace System.Web).

Interoperabilität

Um die Akzeptanz des.NET Framework zu fördern hat Microsoft sinnvoller Weise eine Interoperabilität mit klassischen Windows-Anwendungen und COM-Komponenten sichergestellt. Die CLR ermöglicht sowohl den Aufruf von klassischen C-Style-DLLs (z.B. dem WIN32-API) als auch COM-Komponenten. Andersherum kann eine.NET-Anwendung auch als COM-Komponente aufgerufen werden.

Flexibles Remoting

Der Aufruf von entferntem Code via Remote Procedure Call (RPC) oder dem auf dem RPC aufsetzenden Distributed COM (DCOM) war aufgrund der Komplexität und der mangelnden Durchlässigkeit bei Firewalls bislang sehr unbefriedigend. Das.NET Framework verwendet ein neues, flexibel Remoting-Konzept mit unterschiedlichen Formaten und Transportwegen.

Ein Formatter ist ein Mechanismus, um ein Objekt in einen Bytestrom umzuwandeln bzw. zurückzuwandeln. Man spricht in diesem Zusammenhang auch von Serialisierung/Deserialisierung bzw. Marshaling/Unmarshaling. Microsoft liefert einen Formatter für ein Binäres Format und einen Formatter für das Simple Object Access Protocol (SOAP) mit. Ein Channel bietet ein Transportmedium für serialisierte Objekte an. Microsoft bietet auch hier zwei eingebaute Alternativen: TCP/IP und HTTP.

Die höchste Geschwindigkeit bietet die Kombination: BinaryFormatter und TCP/IP. Für die Überwindung von Firewalls ist SOAP/HTTP die richtige Kombination. Letztere Kombination ermöglicht auch die Nutzung und Bereitstellung von SOAP-basierten Webservices (siehe ì Kapitel 10). Es besteht die Möglichkeit, eigene Formatter oder Channel für.NET zu entwickeln.

Application Domains

Eine Application Domain ist mit dem.NET Framework neu eingeführtes Konzept zur Abgrenzung von Anwendungen. Eine Application Domain ist die Aufteilung eines Prozesses in mehrere Bereiche. Anwendungen, die in verschiedenen Application Domains laufen, sind voneinander genauso isoliert, als liefen sie in verschiedenen Prozessen. Application Domain nennt man auch einen Pseudo-Prozess.

Der Vorteil einer Application Domain gegenüber der Erzeugung verschiederner Prozesse ist, dass der Aufwand zur Erzeugung einer Application Domain und für einen Programmcode-Aufruf zwischen zwei Application Domains geringer ist als für die Verwendung von Prozessen. Mehrere Assemblies können sich eine Application Domain teilen.

Abbildung 8:
Application Domains

 


Autor: Holger Schwichtenberg