Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort zur 5. Auflage
1 Allgemeine Einführung in .NET
2 Grundlagen der Sprache C#
3 Klassendesign
4 Vererbung, Polymorphie und Interfaces
5 Delegates und Ereignisse
6 Weitere .NET-Datentypen
7 Weitere Möglichkeiten von C#
8 Auflistungsklassen (Collections)
9 Fehlerbehandlung und Debugging
10 LINQ to Objects
11 Multithreading und die Task Parallel Library (TPL)
12 Arbeiten mit Dateien und Streams
13 Binäre Serialisierung
14 Einige wichtige .NET-Klassen
15 Projektmanagement und Visual Studio 2010
16 XML
17 WPF – Die Grundlagen
18 WPF-Containerelemente
19 WPF-Steuerelemente
20 Konzepte der WPF
21 Datenbindung
22 2D-Grafik
23 ADO.NET – verbindungsorientierte Objekte
24 ADO.NET – Das Command-Objekt
25 ADO.NET – Der SqlDataAdapter
26 ADO.NET – Daten im lokalen Speicher
27 ADO.NET – Aktualisieren der Datenbank
28 Stark typisierte DataSets
29 LINQ to SQL
30 Weitergabe von Anwendungen
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual C# 2010 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2010

Visual C# 2010
geb., mit DVD
1295 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1552-7
Pfeil 7 Weitere Möglichkeiten von C#
Pfeil 7.1 Namensräume (Namespaces)
Pfeil 7.1.1 Zugriff auf Namespaces
Pfeil 7.1.2 Die »using«-Direktive
Pfeil 7.1.3 Globaler Namespace
Pfeil 7.1.4 Vermeiden von Mehrdeutigkeiten
Pfeil 7.1.5 Namespaces festlegen
Pfeil 7.1.6 Der ::-Operator
Pfeil 7.2 Generics – generische Datentypen
Pfeil 7.2.1 Lösung mit einer generischen Klasse
Pfeil 7.2.2 Typparameter mit Constraints einschränken
Pfeil 7.2.3 Generische Methoden
Pfeil 7.2.4 Generics und Vererbung
Pfeil 7.2.5 Konvertierung von Generics
Pfeil 7.2.6 Generische Delegates
Pfeil 7.2.7 Generische Klassen in der .NET-Klassenbibliothek
Pfeil 7.3 Operatorüberladung
Pfeil 7.3.1 Syntax der Operatorüberladung
Pfeil 7.3.2 Operatorüberladungen in »GeometricObjectsSolution«
Pfeil 7.3.3 »true«- und »false«-Operatoren
Pfeil 7.3.4 Benutzerdefinierte Konvertierungen
Pfeil 7.4 Indexer
Pfeil 7.4.1 Überladen von Indexern
Pfeil 7.4.2 Parameterbehaftete Eigenschaften
Pfeil 7.5 Erweiterungsmethoden
Pfeil 7.6 Implizit typisierte Variablen (Typinferenz)
Pfeil 7.7 Lambda-Ausdrücke
Pfeil 7.8 Anonyme Typen
Pfeil 7.9 Nullable-Typen
Pfeil 7.10 Attribute
Pfeil 7.10.1 Das »Flags«-Attribut
Pfeil 7.10.2 Anmerkungen zu den Attributen
Pfeil 7.10.3 Benutzerdefinierte Attribute
Pfeil 7.10.4 Attribute auswerten
Pfeil 7.10.5 Festlegen der Assembly-Eigenschaften
Pfeil 7.11 Partielle Methoden
Pfeil 7.12 Dynamisches Binden
Pfeil 7.12.1 Eine kurze Analyse
Pfeil 7.12.2 Dynamische Objekte
Pfeil 7.13 Unsicherer (unsafe) Programmcode – Zeigertechnik in C#
Pfeil 7.13.1 Einführung
Pfeil 7.13.2 Das Schlüsselwort »unsafe«
Pfeil 7.13.3 Deklaration von Zeigern
Pfeil 7.13.4 Die »fixed«-Anweisung
Pfeil 7.13.5 Zeigerarithmetik
Pfeil 7.13.6 Der Operator »->«


Galileo Computing - Zum Seitenanfang

7.10 Attribute Zur nächsten ÜberschriftZur vorigen Überschrift

Ein Attribut ist ein Feature von .NET, das einer Komponente Zusatzinformationen bereitstellt oder ein bestimmtes Verhalten signalisiert oder vorgibt. Attribute gehören zu den Metadaten des Programms und werden zur Laufzeit von der CLR (Common Language Runtime) ausgewertet. Dieses Prinzip ist grundsätzlich nicht neu, denken Sie nur an die altbekannten INI-Dateien, die eine ähnliche Zielsetzung hatten. Mit einem Attribut lässt sich das Laufzeitverhalten praktisch aller .NET-Elemente beeinflussen: Assemblys, Klassen, Interfaces, Strukturen, Delegates, Enumerationen, Konstruktoren, Methoden, Eigenschaften, Parameter, Ereignisse, ja sogar die Rückgabewerte von Methoden.

Als Basisklasse aller Attribute dient die abstrakte Klasse Attribute aus dem Namespace System. Wenn Sie in die Online-Dokumentation zum Stichwort Attribute schauen, werden Sie feststellen, dass das .NET Framework sehr viele Attribute vordefiniert, die aus Attribute abgeleitet sind. Alle denkbaren Anforderungen werden damit sicherlich nicht abgedeckt, deshalb können Sie auch benutzerdefinierte Attribute entwickeln und dadurch die Flexibilität Ihrer Anwendung erhöhen.


Galileo Computing - Zum Seitenanfang

7.10.1 Das »Flags«-Attribut Zur nächsten ÜberschriftZur vorigen Überschrift

Wir wollen uns die Wirkungsweise eines Attributs exemplarisch am Attribut FlagsAttribute ansehen, das vom .NET Framework bereitgestellt wird und mit Enumerationen verknüpft wird. Dazu nehmen wir zunächst an, dass eine Enumeration namens Keys die drei Zustandstasten Taste Shift , Taste Strg und Taste Alt beschreibt.


public enum Keys {
  Shift = 1,
  Ctrl = 2,
  Alt = 4
}

Wird diese Enumeration um FlagsAttribute erweitert, geben wir an, dass die Aufzählung als Kombination von Bits aufgefasst werden kann. Das Attribut wird in C# in eckige Klammern gefasst.


[FlagsAttribute]
public enum Keys {
  Shift = 1,
  Ctrl = 2,
  Alt = 4
}

Wir können nun eine Variable vom Typ Keys deklarieren und ihr einen Wert zuweisen, der den Zustand der beiden gleichzeitig gedrückten Tasten Taste Strg und Taste Shift beschreibt. Beide verknüpfen wir mit dem |-Operator:


Keys tastenkombination = Keys.Ctrl | Keys.Shift;

Mit den bitweisen Operatoren kann nun natürlich auch geprüft werden, ob der Anwender eine bestimmte Taste oder gar Tastenkombination gedrückt hat:


Keys tastenkombination = Keys.Ctrl | Keys.Shift;
if ((tastenkombination & Keys.Alt) == Keys.Alt)
  Console.WriteLine("Alt gedrückt");
else
  Console.WriteLine("Alt nicht gedrückt");

Hier wird natürlich die Ausgabe lauten, dass die Taste Alt -Taste nicht gedrückt ist. Eine ähnliche Enumeration, die dann allerdings jede Taste der Tastatur beschreibt, gibt es im Namespace System.Windows.Forms.

Wenn wir uns nun den Inhalt der Variablen tastenkombination mit


Console.WriteLine(tastenkombination.ToString());

ausgeben lassen, indem wir ToString an der Konsole aufrufen, erhalten wir:


Shift, Ctrl

Hätten wir FlagsAttribut nicht gesetzt, würde die Ausgabe 3 lauten. Sie müssen berücksichtigen, dass die Mitglieder solchermaßen definierter Enumerationen Zweierpotenzen sind (also 1, 2, 4, 8, 16, 32, 64 ...). Alternativ sind auch hexadezimale Zahlenwerte zulässig.

Attribute setzen

Attributsbezeichner enden immer mit dem Suffix Attribute. Wird ein Attribut mit einem Element verknüpft, darf auf das Suffix Attribute verzichtet werden. Bezogen auf unser Beispiel dürfen Sie also


[FlagsAttribute]
public enum Keys {
  ...
}

und


[Flags]
public enum Keys {
  ...
}

gleichwertig verwenden. Bemerkt die Laufzeit die Verknüpfung eines Attributs mit einem Element, sucht sie nach einer Klasse, die mit dem angegebenen Attributbezeichner übereinstimmt und gleichzeitig die Klasse Attribute ableitet, also beispielsweise nach einer Klasse namens Flags. Wird die Laufzeit nicht fündig, hängt sie automatisch das Suffix Attribute an den Bezeichner an und wiederholt die Suche.

Sie können auch mehrere Attribute gleichzeitig setzen. Beispielsweise könnten Sie mit dem ObsoleteAttribute das Element zusätzlich als veraltet kennzeichnen, z. B. so:


[FlagsAttribute]
[Obsolete("Diese Enumeration ist veraltet.");
 public enum Keys {
  ...
}


Galileo Computing - Zum Seitenanfang

7.10.2 Anmerkungen zu den Attributen Zur nächsten ÜberschriftZur vorigen Überschrift

Das Attribut [Flags] erinnert in seiner Wirkungsweise eher an eine boolesche Variable, die gesetzt ist oder nicht. Weist eine Enumeration dieses Attribut auf, lassen sich die Elemente der Aufzählung bitweise miteinander kombinieren. Sehr ähnlich verhalten sich auch viele andere Attribute der .NET-Klassenbibliothek. Das sehr häufig verwendete Attribut SerializableAttribute kennzeichnet beispielsweise eine Klasse als binär serialisierbar.

Jedes .NET-Projekt weist neben den Quellcodedateien auch die Datei AssemblyInfo.cs auf, die Metadaten über die Assemblierung beschreibt. Dazu gehören Versionsinformationen, Titel und Copyright-Hinweise. Diese Zusatzinformationen werden ebenfalls über Attribute bereitgestellt und können direkt in AssemblyInfo.cs eingetragen werden. Die Daten werden zur Laufzeit ausgewertet, wie auch die aller anderen Attribute.

Attribute basieren auf Klassendefinitionen und können daher alle klassentypischen Elemente enthalten. Dazu gehören neben Konstruktoren auch Felder. Insbesondere diese beiden Elemente ermöglichen es, über ein Attribut dem attributierten Element Zusatzinformationen bereitzustellen. Wie das in der Praxis aussieht, wollen wir uns am Beispiel eines benutzerdefinierten Attributs verdeutlichen.


Galileo Computing - Zum Seitenanfang

7.10.3 Benutzerdefinierte Attribute Zur nächsten ÜberschriftZur vorigen Überschrift

Obwohl das .NET Framework zahlreiche Attribute vordefiniert, können Sie auch für eigene Zwecke Attributklassen selbst schreiben. Allerdings müssen Sie für die Auswertung des Attributs zur Laufzeit auch selbst sorgen.

Drei Punkte müssen Sie beachten, um ein benutzerdefiniertes Attribut zu codieren:

  • Der Definition eines benutzerdefinierten Attributs selbst geht immer die Definition des Attributs AttributeUsageAttribute voraus.
  • Die Klasse wird aus Attribute abgeleitet.
  • An den Klassenbezeichner sollte das Suffix Attribute angehängt werden.

Lassen Sie uns an dieser Stelle exemplarisch ein eigenes Attribut erstellen, dessen Aufgabe es ist, sowohl den Entwickler einer Klasse oder Methode als auch dessen Personalnummer anzugeben. Das folgende Beispiel zeigt die noch unvollständige Definition der Attributklasse:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
                Inherited = false,  
                AllowMultiple = false)] 
public class DeveloperAttribute : Attribute 
{
  ...
}

Die Voranstellung des Attributs AttributeUsage vor die Klasse sorgt dafür, bereits hier elementare Eigenschaften der neuen Attributklasse festzulegen. In diesem Zusammenhang sind drei Parameter besonders interessant:

  • AttributeTargets
  • Inherited
  • AllowMultiple

Während AttributeTargets angegeben werden muss, sind die beiden anderen optional.

AttributeTargets

Jedes Attribut kann sich nur auf bestimmte Codeelemente auswirken. Diese werden mit AttributeTargets bekannt gegeben. Im Beispiel oben wird mit AttributeTargets.All zum Ausdruck gebracht, dass wir das benutzerdefinierte Attribut auf alle Elemente anwenden können, aber das muss nicht immer so sein. Man kann den Einsatz eines Attributs ebenso gut nur auf Methoden oder Felder beschränken. Es steht dabei immer folgende Frage im Vordergrund: Was soll das Attribut letztendlich bewirken, welche Elemente sollen über das Attribut beeinflusst werden?

AttributeTargets ist in der .NET-Klassenbibliothek als Enumeration vordefiniert und enthält die in Tabelle 7.4 aufgeführten Entitäten.


Tabelle 7.4 Mitglieder der »AttributeTargets«-Enumeration

Mitglieder Beschreibung
All

Das Attribut gilt für jedes Element der Anwendung.

Assembly

Das Attribut gilt für die Assemblierung.

Class

Das Attribut gilt für die Klasse.

Constructor

Das Attribut gilt für den Konstruktor.

Delegate

Das Attribut gilt für das Delegate.

Enum

Das Attribut gilt für die Enumeration.

Event

Das Attribut gilt für das Ereignis.

Field

Das Attribut gilt für das Feld.

Interface

Das Attribut gilt für die Schnittstelle.

Method

Das Attribut gilt für die Methode.

Module

Das Attribut gilt für das Modul.

Parameter

Das Attribut gilt für den Parameter.

Property

Das Attribut gilt für die Property.

ReturnValue

Das Attribut gilt für den Rückgabewert.

Struct

Das Attribut gilt für die Struktur.


Natürlich steht auch hinter AttributeUsageAttribute eine Klassendefinition, die im Namespace System zu finden ist. Im Grunde genommen unterscheidet sich eine Klasse, die ein Attribut beschreibt, nicht von einer herkömmlichen Klasse. Daher verwundert es nicht, dass die Klasse AttributeUsageAttribute einen Konstruktor definiert, der einen Parameter vom Typ AttributeTargets erwartet:


public AttributeUsageAttribute(AttributeTargets validon);

Der Parameter validon vom Typ AttributeTargets wird bitweise interpretiert. Jedes Bit beschreibt dabei ein Element, auf das das Attribut angewendet werden kann. Möchten Sie das Attribut mehreren verschiedenen Elementen zugänglich machen, müssen Sie mehrere AttributeTargets-Konstanten bitweise verknüpfen, z. B. so:


[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]

In diesem Fall wird ein Attribut bereitgestellt, das sowohl Methoden als auch Eigenschaften als Informationsquelle dienen kann.

Inherited

Eine Klasse kann ihre Mitglieder einer abgeleiteten Klasse vererben. Einem Entwickler stellt sich natürlich die Frage, ob das Attribut in den Vererbungsprozess mit einbezogen wird oder ob es Gründe gibt, es davon auszuschließen. Einem benutzerdefinierten Attribut teilen wir dies durch den booleschen Parameter Inherited mit, den wir optional AttributeUsageAttribute übergeben können. Standardmäßig ist der Wert auf true festgelegt. Demnach vererbt sich ein gesetztes Attribut in einer Vererbungshierarchie weiter.

AllowMultiple

In wohl eher seltenen Fällen kann es erforderlich sein, ein Attribut demselben Element mehrfach zuzuweisen. Diese Situation wäre denkbar, wenn man über das Attribut einem Element mehrere Feldinformationen zukommen lassen möchte. Dann muss man die mehrfache Anwendung eines Attributs explizit gestatten. Zur Lösung geben Sie den Parameter


AllowMultiple = true

an. Verzichten Sie auf diese Angabe, kann ein Attribut per Definition mit einem bestimmten Element nur einmal verknüpft werden.

Konstruktoren eines Attributs

Sie können in Attributklassen öffentliche Felder und Eigenschaften definieren, deren Werte an den Benutzer des Attributs weitergeleitet werden. Initialisiert werden die Felder über Konstruktoren. Unser DeveloperAttribute soll mit Name und Identifier zwei Felder beschreiben. Das erstgenannte Feld wird beim Konstruktoraufruf initialisiert.


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DeveloperAttribute : Attribute {
  public string Name;
  public int Identifier;
  public DeveloperAttribute(string name) {
    Zuname = name;
  }
}

Der Konstruktor nimmt einen Parameter entgegen, nämlich den Wert für das Feld Name. Bevor Sie sich darüber Gedanken machen, wie man das Feld Identifier initialisiert, sollten Sie sich ansehen, wie das Attribut auf eine Klasse angewendet wird:


[DeveloperAttribute("Meier")] 
public class Demo {
  ...
}

Mit dieser Definition wird der Konstruktor unter Übergabe einer Zeichenfolge aufgerufen. Das zweite Feld des Attributs (Identifier) wird mit keinem bestimmten Wert initialisiert, es enthält 0. Selbstverständlich könnten wir innerhalb der Attributdefinition für Identifier einen von 0 abweichenden Wert festlegen, aber dieser ist dann natürlich für jedes verknüpfte Element identisch.

Positionale und benannte Parameter

Um Identifier einen individuellen Wert zuzuweisen, können Sie DeveloperAttribute auch wie folgt mit der Klasse verknüpfen:


[DeveloperAttribute("Meier", Identifier = 8815)] 
public class Demo {
  ...
}

Beachten Sie, dass wir jetzt zwei Argumente übergeben, obwohl der Konstruktor nur einen Parameter vorsieht. Dies ist ein besonderes Merkmal der Attribute, denn beim Initialisieren eines Attributs können Sie sowohl positionale als auch benannte Parameter verwenden.

  • Positionale Parameter sind die Parameter für den Konstruktoraufruf und müssen immer angegeben werden, wenn das Attribut gesetzt wird. Benannte Parameter sind optionale Parameter. In unserem Beispiel ist Name ein positionaler Parameter, dem die Zeichenfolge »Meier« übergeben wird, während Identifier ein benannter Parameter ist.
  • Benannte Parameter sind sehr flexibel. Einerseits können sie Standardwerte aufweisen, die grundsätzlich immer gültig sind, andererseits kann der Wert im Bedarfsfall individuell festgelegt werden.

Ob Sie ein Attributfeld positional oder benannt einsetzen wollen, ist eine Entscheidung, die sich an den spezifischen Anforderungen orientiert. Ob ein benannter Parameter neu festgelegt werden muss oder ob der Standardwert akzeptabel ist, hängt vom Einzelfall ab.

Die Möglichkeit, benannte Parameter vorzusehen, befreit Sie von der Verpflichtung, für jede denkbare Kombination von Feldern und Eigenschaften überladene Konstruktoren in der Attributdefinition vorsehen zu müssen. Andererseits wird Ihnen damit aber nicht die Alternative entzogen, dennoch den Konstruktor zu überladen. Da unterscheiden sich die herkömmlichen Klassendefinitionen nicht von denen der Attribute.

Wenn Sie ein Attribut mit einem Element verknüpfen und dabei positionale und benannte Parameter verwenden, müssen Sie eine wichtige Regel beachten: Zuerst werden die positionalen Parameter aufgeführt, danach die benannten. Die Reihenfolge der benannten Parameter ist beliebig, da der Compiler aufgrund der Parameternamen die angegebenen Werte richtig zuordnen kann. Benannte Parameter können alle öffentlich deklarierten Felder oder Eigenschaften sein – vorausgesetzt, sie sind weder statisch noch konstant definiert.


Galileo Computing - Zum Seitenanfang

7.10.4 Attribute auswerten Zur nächsten ÜberschriftZur vorigen Überschrift

Vermutlich werden Sie sich jetzt fragen, was ein Attribut bewirkt, welchen Sinn es also hat, ein Attribut zu setzen. Im Grunde genommen ist die Antwort ganz einfach. Viele Methoden im .NET Framework verlangen zur Ausführung ihrer Operation, dass das betroffene Element mit einem bestimmten Attribut versehen ist. Beispielsweise können Sie eine Klasse nur dann binär serialisieren, wenn der Klasse das Attribut Serializable angeheftet ist. Ansonsten ist eine binäre Serialisierung nicht möglich. Sehr ähnlich agiert auch das Flags-Attribut. Nur wenn es gesetzt ist, lassen sich die beiden Operanden bitweise kombinieren. Ein Attribut hat demnach einen steuernden Einfluss auf das Laufzeitverhalten eines Elements und versorgt es möglicherweise mit essenziellen Informationen.

Operationen, die auf die Existenz eines Attributs angewiesen sind, müssen zuerst feststellen, ob das erforderliche Attribut gesetzt ist oder nicht. Im folgenden Beispielprogramm soll dies für das Beispiel unseres eben entwickelten DeveloperAttributes gezeigt werden. Beachten Sie hier bitte, dass der Namespace System.Reflection bekannt gegeben werden muss.


// ---------------------------------------------------------
// Beispiel: ...\Kapitel 7\AttributeDemo
// ---------------------------------------------------------
using System.Reflection;
[Developer("Meier")]
class Demo {
  [Developer("Fischer", Identifier=455)]
  public void DoSomething() { }
  public void DoMore() { }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DeveloperAttribute : Attribute {
  public string Name;
  public int Identifier;
  public DeveloperAttribute(string name) {
    Name = name;
  }
}
class Program {
  static void Main(string[] args) {
    Type tDemo = typeof(Demo);
    Type tAttr = typeof(DeveloperAttribute);         
    MethodInfo mInfo1 = tDemo.GetMethod("DoSomething");
    MethodInfo mInfo2 = tDemo.GetMethod("DoMore");
    // Prüfen, ob das Attribut bei der Klasse 'Demo' gesetzt ist
    DeveloperAttribute attr =  
      (DeveloperAttribute)Attribute.GetCustomAttribute(tDemo, tAttr);
    if (attr != null) {
      Console.WriteLine("Name: {0}", attr.Name);
      Console.WriteLine("Identifier: {0}", attr.Identifier);
    }
    else
      Console.WriteLine("Attribut nicht gesetzt");
    // Prüfen, ob das Attribut bei der Methode 'DoSomething' gesetzt ist
    attr = (DeveloperAttribute)Attribute.GetCustomAttribute(mInfo1, tAttr);
    if (attr != null) {
      Console.WriteLine("Name: {0}", attr.Name);
      Console.WriteLine("Identifier: {0}", attr.Identifier);
    }
    // Prüfen, ob das Attribut bei der Methode 'DoMore' gesetzt ist
    bool isDefinied = Attribute.IsDefined(mInfo2, tAttr);
    if (isDefinied)
      Console.WriteLine("DoMore hat das Attribut.");
    else
      Console.WriteLine("DoMore hat das Attribut nicht.");
    Console.ReadLine();
  }
}

Das benutzerdefinierte Attribut DeveloperAttribut ist identisch mit demjenigen, das wir bereits vorher in diesem Abschnitt behandelt haben. Es kann mit einer Klasse oder einer Methode verknüpft werden. Die Klasse Demo, die dieses Attribut aufweist, enthält mit DoSomething und DoMore zwei Methoden, von denen nur die erstgenannte mit dem Attribut verknüpft ist.

Um die Frage zu beantworten, ob ein bestimmtes Element mit dem DeveloperAttribute verknüpft ist oder nicht, greifen wir auf die Möglichkeiten einer Technik zurück, die als Reflection bezeichnet wird. Die Reflection gestattet es, die Metadaten einer .NET-Assembly und der darin enthaltenen Datentypen zu untersuchen und auszuwerten. Zur Abfrage von Attributen stellt die Reflection die Klasse Attribute mit der statischen Methode GetCustomAttribute bereit. Da wir sowohl die Klasse als auch die Methoden untersuchen wollen, müssen wir auf zwei verschiedene Überladungen zurückgreifen. Für die Klasse ist es die folgende:


public static Attribute GetCustomAttribute(Module, Type);

Um eine Methode zu untersuchen, ist es die folgende Überladung:


public static Attribute GetCustomAttribute (MemberInfo, Type);

Im ersten Argument geben wir den Typ des zu untersuchenden Elements an, im zweiten Parameter den Typ des Attributs. Um den Typ mithilfe von Code zu beschreiben, wird von der Reflection die Klasse Type bereitgestellt. Diese beschreibt den Datentyp und kann auf zweierlei Art und Weise erzeugt werden:

  • unter Verwendung des Operators typeof, dem der Typbezeichner übergeben wird
    (z. B. typeof(Demo))
  • durch Aufruf der Methode GetType() auf einer Objektreferenz
    (z. B. myObject.GetType())

Um die Attribute einer Klasse auszuwerten, übergeben Sie der Methode GetCustomAttribute nur den Type der Klasse und den Type des gesuchten Attributs. Zur Auswertung einer Methode ist ein MemberInfo-Objekt erforderlich. MemberInfo ist eine abstrakte Klasse im Namespace System.Reflection. Wir erhalten die Metadaten der zu untersuchenden Methode, wenn wir die Methode GetMethod des Type-Objekts unter Angabe des Methodenbezeichners aufrufen. Der Typ der Rückgabe ist MethodInfo, eine von MemberInfo abgeleitete Klasse.

Der Typ der Rückgabe der beiden Überladungen von GetCustomAttribute ist Attribute. Dabei handelt es sich entweder um die Referenz auf das gefundene Attribut oder um null, falls das Attribut nicht mit dem im ersten Parameter angeführten Element verknüpft ist. Daher erfolgt zuerst eine Konvertierung in das Zielattribut und anschließend eine Überprüfung, ob der Rückgabewert null ist.


DeveloperAttribute attr = (DeveloperAttribute)Attribute.GetCustomAttribute(tDemo, tAttr);
if (attr != null) {
  Console.WriteLine("Name: {0}", attr.Name);
  Console.WriteLine("Identifier: {0}", attr.Identifier;
}
else
  Console.WriteLine("Attribut nicht gesetzt");

Da wir bei der Implementierung von Main wissen, dass nur unser benutzerdefiniertes Attribut DeveloperAttribute gesetzt ist (oder auch nicht), genügt uns diese Untersuchung. Ein Element kann natürlich auch mit mehreren Attributen verknüpft sein. Im Code müssten wir dann die Elemente auf alle gesetzten Attribute abfragen.


Galileo Computing - Zum Seitenanfang

7.10.5 Festlegen der Assembly-Eigenschaften topZur vorigen Überschrift

Weiter oben habe ich kurz die Datei AssemblyInfo.cs erwähnt. Ganz allgemein dient diese Datei dazu, Zusatzinformationen zu der aktuellen Assemblierung bereitzustellen, beispielsweise eine Beschreibung, Versionsinformationen, Firmenname, Produktname und mehr. Diese werden im Windows Explorer in den Dateieigenschaften angezeigt. Da die Informationen die Assemblierung als Ganzes betreffen, müssen die Deklarationen außerhalb einer Klasse stehen und dürfen auch nur einmal gesetzt werden.


[assembly: AssemblyTitle("AssemblyTitle")]
[assembly: AssemblyDescription("AssemblyDescription")]
[assembly: AssemblyConfiguration("AssemblyConfiguration")]
[assembly: AssemblyCompany("Tollsoft")]
[assembly: AssemblyProduct("AssemblyProduct")]
[assembly: AssemblyCopyright("Copyright ©Tollsoft 2008")]
[assembly: AssemblyTrademark("AssemblyTrademark")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("948efa6b-af3a-4ba2-8835-b54b058015d4")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Sie können die gewünschten Assembly-Informationen in der Datei AssemblyInfo.cs eintragen, Sie können aber auch die Einträge im Eigenschaftsdialog des Projekts vornehmen. Dazu öffnen Sie das Eigenschaftsfenster des Projekts und wählen die Lasche Anwendung. Auf dieser Registerkarte sehen Sie die Schaltfläche Assembly-Information…, über die der Dialog aus Abbildung 7.4 geöffnet wird.

Abbildung 7.4 Eintragen der Assembly-Informationen in Visual Studio 2010



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual C# 2010

Visual C# 2010
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: C/C++






 C/C++


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2010
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern