Delphi-PRAXiS :: Das Forum für Fragen zu Delphi
Das Experten Forum für Delphi Programmierer
Hilfe für CodeGear Delphi gibts es hier im Forum
Delphi Quelltexte und Source Codes
 
Delphi-PRAXiS :: Foren-ÜbersichtForen-Übersicht Delphi-PRAXiS Modul-ÜbersichtSite-Map Delphi-PRAXiS durchsuchenSuchen Delphi-PRAXiS Code-LibraryCode-Library Jetzt registrieren!Registrieren Login  
   
 
0
 
Delphi für Win32
[BorCon] Einführung in die .NET Framework Klassen Bibliothek
Ein Delphi (Win32)-Thema von sakura.

Vorheriges Thema anzeigen  |  Nächstes Thema anzeigen
Neuen Beitrag schreiben Dieses Thema ist gesperrt, Du kannst keine Beiträge editieren oder beantworten.
als PDF-Datei herunterladenThema ausdrucken
 
Delphi-PRAXiS Forum - Übersicht -> Tutorials und Kurse
Seite 1 von 1   [ 10 Beiträge ]  
 
 Autor 
 Nachricht 
 
sakura #1|Beitrag #248250Verfasst am: 11.10.2004, 13:43      Titel: [BorCon] Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Sprache: Delphi (Win32)

Ich habe von Corbin Dunn die schriftliche Genehmigung seinen Artikel Introduction to the .NET Framework Class Library für die Delphi-PRAXiS ins Deutsche zu übersetzen. Folgend also die unkommentierte (und hoffentlich korrekte) Übersetzung. Wer Fragen zu diesem Artikel hat, möge diese bitte in einen eigenen Thread posten.

...Cat...

 Zuletzt bearbeitet von sakura am 11.10.2004, 15:39, insgesamt 1-mal bearbeitet.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #2|Beitrag #248255Verfasst am: 11.10.2004, 13:44      Titel: Re: Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Einführung in die .NET Framework Klassen Bibliothek
von Corbin Dunn (BorCon 2004)
Borland R&D Software Engineer


Die .NET Framework Klassen Bibliothek (FCL) besteht aus einer Reihe von Klassen, Schnittstellen (Interfaces) und Wertetypen welche in eigenen Anwendungen eingesetzt werden können. Das .NET Framework bietet Typen die einem folgende Möglichkeiten bieten:
  • Erstellung extravaganter Benutzeroberflächen (GUI) (System.Windows.Forms)
  • Zugriff und Manipulation von Daten in verschiedenen Datenbanken (System.Data und System.Xml)
  • Dynamische Abfrage von Typen Informationen (System.Reflection)
  • Durchführung grundlegender Ein- und Ausgaberoutinen (System.IO)
  • Überprüfung der Rechte innerhalb des Betriebssystems (System.Security)
  • Erstellung von Internetanwendungen (System.Net und System.Net.Sockets)
  • Erstellung dynamischer internetbasierter Anwendungen - auch bekannt als ASP.NET (System.Web)
  • Zugriff auf allgemeine Datentypen, Ereignisshandler und Fehler (System)


Alle Typen der FCL sind kompatibel zur Common Language Specification (Allgemein Sprachspezifikationen, CLS). Das ermöglicht es jeder CLS-kompatiblen Entwicklungsumgebung (z.B. Delphi, C# und VB) diese Typen zu nutzen.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #3|Beitrag #248257Verfasst am: 11.10.2004, 13:46      Titel: Re: Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Basis Namensräume und Typen der FCL


Jede Klasse ist in einem Namensraum (Namespace) untergebracht, welcher ihren Zweck sinnvoll beschreibt, und im .NET Framework gibt es viele Namensräume. A grundlegender, vollständig qualifizierter Klassenname ist System.Collections.ArrayList. Der Teil links vom letzten Punkt ist i.A. der Namensraum, der rechte Teil ist der Klassenname (Notiz 1). Alle Klassen der FCL sind im Root-Namensraum System untergebracht. Klassen von Drittanbietern sollten, wenn möglich, innerhalb eines Namensraum mit folgendem Format Firmenname.Technologiename untergebracht sein. Zum Beispiel: Borland.Delphi.System ist der vollständig qualifizierte Name der Delphi System Unit.

Die FCL basiert auf dem Common Type System (allgemeines Typensystem, siehe CLS). Das Common Type System ermöglicht es der FCL mit verschiedenen Sprachen in der "verwalteten Laufzeitumgebung" (Managed Runtime) zu operieren.

Wertetypen (Value Types) vs. Refenztypen (Reference Types)

Wertetype sind direkt für ihre Werte verantwortlich und i.A. auf dem Stack hinterlegt. Referenztypen speichern eine Referenz (Zeiger, Verweis) auf deren Daten und sind auf dem Heap gesichert. Wertetypen sind allgemein primitive Typen, wie z.B. ordinale Typen. Referenztypen hingegen sind i.A. Objekte, wie z.B. System.Windows.Forms.Control. Die Änderung eines Werte in einem Wertetypen verändert nur die spezielle Instanz dieses Werte, da diese eine Kopie ihres Wertes enthalten.
Folgendes C# Beispiel soll das verdeutlichen:
Code: markieren
Point firstPoint = new Point(5, 5);
      Point secondPoint = firstPoint;
      firstPoint.X = 6;

In der zweiten Zeile wird secondPoint der Wert von firstPoint zugewiesen; es wird eine Kopie des Werte von firstPoint hinterlegt. Dieser hat die Werte X=5 und Y=5. In der dritten Zeile wird firstPoint.X der Wert 6 zugewiesen. Das verändert nur den Wert in firstPoint.X, secondPoint.X hält weiterhin den Wert 5.

Betrachten wir nun folgenden C# Code:
Code: markieren
Control firstControl = new Control();
      Control secondControl = firstControl;
      firstControl.BackColor = Color.Red;

In der zweiten Zeile wird secondControl ein Verweis auf auf firstControl zugewiesen. Die Veränderung des Wertes firstControl.BackColor in der dritten Zeile verändert daher auch den Wert in secondControl.BackColor da der Wert von Typ Control ein Referenzwert ist.

In der FCL sind alle Basistypen, wie z.B. Integer und Boolean (auch Aufzählungen), Wertetypen. Fast alle anderen Klassen sind in der Regel Referenztypen, so auf System.String. In der Programmierung wird ein Wertetyp durch struct (in C#) oder record (in Delphi) erstellt, Referenztypen hingegen werden mit Hilfe von class erstellt.

Das Boxing von Typen

Es ist in .NET möglich Wertetypen in Referenztypen (und zurück) umzuwandeln. Dazu folgendes C# Beispiel:
Code: markieren
object obj = null; // a reference type
      int i = 5; // a value type
      obj = i; // boxing
      //i = obj; // compiler error
      i = (int)obj; // unboxing: the value type is copied to i

In der dritten Zeile wird der Wertetype implizit als Referenztyp "geboxt". In C# kann man Objekttypen nicht Wertetypen zuweisen, deshalb würde die vierte Zeile auch einen Compiler-Fehler provozieren. Man muss den Wert explizit als Wertetyp darstellen, dadurch wird der Wert kopiert.

Beachte, dass Delphi selbst als sehr typensicher gilt und betrachte den folgenden (zu oben analogen) Delphi.NET Quellcode:
Delphi-Quellcode: markieren
var
  I: Integer;
  Obj: TObject;
begin
  I := 5;
  Obj := I; // Compiler error: Incompatible types
//  I := Obj; // Expected compiler error
  I := Integer(Obj);
end.

Obiger Code lässt sich in Delphi nicht kompilieren, da in der zweiten Zeile die Typensicherheit nicht gewährleistet wird. In diesem Fall gibt es für den Delphi-Programmierer zwei Lösungsmöglichkeiten. Entweder durch explizites casten des Wertes in ein TObject:
Delphi-Quellcode: markieren
Obj := TObject(I);

oder durch den Compilerschalter AUTOBOX, welcher irgenwo vor der "Problemzeile" erscheinen muss:
Delphi-Quellcode: markieren
{$AUTOBOX ON}

Der Compilerschalter AUTOBOX zwingt den Delphi-Compiler weniger typensicher zu agieren und lässt Delphi so etwas mehr wie C# erscheinen. Die Nutzung kann die Programmierung erleichtern, allerdings kann es auch schneller zu Programmierfehlern führen.

Schnittstellentypen (Interface Types)

In der FCL existieren viele Interfacetypen und diese kann man auch in gewohnter Art und Weise einsetzen. Interfaces sind abstrakte Deklarationen welche durch Klassen (Referenztypen) implementiert werden.

(Notiz 1) Eine Ausnahme zu dieser Regel sind verschachtelte Typen.

 Zuletzt bearbeitet von sakura am 11.10.2004, 13:51, insgesamt 1-mal bearbeitet.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #4|Beitrag #248261Verfasst am: 11.10.2004, 13:50      Titel: Re: Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

System.Delegate und System.EventHandler


Die FCL bietet Delegate, diese sind verwaltete Zeiger (managed pointer) welche eingesetzt werden können um Ereignishandler und Callback-Funktionen im .NET Framework zu nutzen. Die Standardimplementierung von System.Delegate ermöglicht es einem Delegat hinzuzufügen bzw. zu entfernen, sowie die darin enthaltenen Methoden.

System.Delegate ist die Basisklasse für alle Delegate. System.MulticaseDelegate ist von System.Delegate abgeleitet und bietet die Möglichkeit mehrere Methode aufzurufen. Wenn ein Delegat nicht von System.MulticastDelegate abgeleitet ist, so kann es nur max. eine Referenz auf eine Methode enthalten.

Eigene Delegate erstellen

Jeder .NET compiler sollte die Unterstützung von Delegaten über Schlüsselwörter oder eine spezielle Syntax unterstützen. C# bietet das Schlüsselwort delegate:
Code: markieren
public delegate void SampleEventHandler(object sender, EventArgs args);

Beachte, dass der Delegate-Name auf EventHandler endet. Das ist ein Standard und Microsoft empfiehlt alle Delegate so zu benennen, es ist jedoch keine Pflicht.

Weiterhin gilt es zu beachten, dass die Signatur des Delegats keinen Rückgabewert hat, der erste Parameter vom Typ object ist und der zweite Parameter vom Typ EventArgs. Diese Signatur trifft man sehr häufig in der FCL an und wird auch von Microsoft empfohlen, wiederum ist auch dieses keine Verpflichtung. Wie auch immer, diese Signatur wird so häufig genutzt, dass sie ihr eigenes Delegat besitzt: System.EventHandler. Durch Festlegung ist der erste Parameter immer die Instanz, welche die Methode aufgerufen hat. Der zweite Parameter enthält die Argumente, welche das Ereignis beschreiben.

Wenn man mehr Informationen an ein Delegat weiterleiten möchte, kann man eine eigene Klasse von EventArgs ableiten und die benötigten Eigenschaften darin definieren:
Code: markieren
public class MyEventArgs : EventArgs
{
      public MyEventArgs(string mySpecialValue)
      {
            MySpecialValue = mySpecialValue;
      }
      public string MySpecialValue;
}
public delegate void SampleSpecialEventHandler(object sender, MyEventArgs args);

Wenn das Delegat aufgerufen wird, dann kann die aufgerufene Methode auf args.MySpecialValue zugreifen.

Einen eigenen Delegat in Delphi zu erstellen ist recht einfach und bekannt, einfach die bekannte Methodentypendeklaration nutzen:
Delphi-Quellcode: markieren
type
  TSampleEventHandler = procedure(Sender: TObject; Args: EventArgs);


Erstellen und Nutzen eines Delegates
In C# erstellt man ein Multicast-Delegat mit Hilfe des Schlüsselwortes event:
Code: markieren
public event SampleEventHandler EventTest;

Will man einem Ereignis einen (weiteren) Ereignishandler zufügen, so muss man in C# die += Syntax nutzen:
Code: markieren
private void WinForm_Load(object sender, System.EventArgs e)
      {
            EventTest += new SampleEventHandler(OnMyEvent);
      }

      private void OnMyEvent(object sender, EventArgs args)
      {
            MessageBox.Show("OnMyEvent called!");
      }

Der C# Compiler erkennt die Zuweisung und ersetzt die += Syntax intern durch einen Aufruf zu System.Delegate.Combine, um SampleEventHandler der Liste in EventTest hinzuzufügen. Es ist in C# möglich dieses Konstrukt auch zu erweitern und wie folgend zu schreiben:
Code: zusammenfalten | markieren
// Example of how to "roll out" an event handler
private SampleEventHandler otherEvent;
private event SampleEventHandler AnotherEventTest
{
  add
  {
    otherEvent =
       (SampleEventHandler)Delegate.Combine(otherEvent, value);
  }

  remove
  {
    otherEvent =
      (SampleEventHandler)Delegate.Combine(otherEvent, value);
  }
}

Beachte die Nutzung von Delegate.Combine und die implizite Übergabe des Wertetypen als Parameter.

Die allgemeine Art einen einfachen Ereignisshandler in Delphi zu schreiben sieht wie folgend aus:
Delphi-Quellcode: zusammenfalten | markieren
type
  TSampleEventHandler = procedure(Sender: TObject; Args: EventArgs);

  TWinForm18 = class(System.Windows.Forms.Form)
  private
    FSingleSampleEventHandler: TSampleEventHandler;

    property SampleEventHandler: TSampleEventHandler
      read FSingleSampleEventHandler write FSingleSampleEventHandler;
  end;

Um mehrfache (multi-cast) Ereignishandler zu schreiben muss man die Schlüsselwörter add und remove nutzen:
Delphi-Quellcode: zusammenfalten | markieren
type
  TSampleEventHandler = procedure(Sender: TObject; Args: EventArgs);

  TWinForm18 = class(System.Windows.Forms.Form)
  private
    FMultiSampleEventHandler: TSampleEventHandler;

    property MultiSampleEventHandler: TSampleEventHandler
      add FMultiSampleEventHandler remove FMultiSampleEventHandler;   
  end;

Anstelle der (neuen) Standardsyntax für Mehrfach-Ereignishandler (hier FMultiSampleEventHandler) kann man die Implementierung auch manuell gestallten:
Delphi-Quellcode: zusammenfalten | markieren
FMultiSampleEventHandlerByHand: TSampleEventHandler;
    { Multi-cast event handler roll out methods }
    procedure AddMultiEvent(Value: TSampleEventHandler);
    procedure RemoveMultiEvent(Value: TSampleEventHandler);
    { Multi-cast event, rolled out by hand }
    property MultiSampleEventHandlerByHand: TSampleEventHandler
      add AddMultiEvent remove RemoveMultiEvent;

// Die Implementierung gestalltet sich etwas umständlich, wenn man die Syntax dafür nicht kennt:

procedure TWinForm18.AddMultiEvent(Value: TSampleEventHandler);
begin
  FMultiSampleEventHandlerByHand := TSampleEventHandler(
    Delegate.Combine(@FMultiSampleEventHandlerByHand, @Value));
end;

procedure TWinForm18.RemoveMultiEvent(Value: TSampleEventHandler);
begin
  FMultiSampleEventHandlerByHand := TSampleEventHandler(
    Delegate.Remove(@FMultiSampleEventHandlerByHand, @Value));
end;

Man beachte den Einsatz von @, um die Adresse des Ereignisses zu ermitteln; wird @ nicht genutzt, wird der Ereignishandler direkt aufgerufen. Man beachte auch den Cast des Ereignistypen, genauso wie auch in C#.

In Delphi kann man weiterhin die Standard Art nutzen, um einen Ereignishandler zu setzen:
Delphi-Quellcode: markieren
procedure TWinForm18.TWinForm18_Load(sender: System.Object;
  e: System.EventArgs);
begin
  SampleEventHandler := OnSampleEvent;
end;


Will man jedoch auf mulit-casts nicht verzichten, so muss man Include(...) nutzen:
Delphi-Quellcode: markieren
procedure TWinForm18.TWinForm18_Load(sender: System.Object;
  e: System.EventArgs);
begin
  Include(MultiSampleEventHandler, OnSampleEvent);
end;


Um einen Ereignishandler zu entfernen muss man Exclude(...) nutzen.

Der Aufruf der Ereignishandler gestaltet sich in Delphi ähnlich wie in C#. Zuerst muss man überprüfen, ob der Handler nil ist, anschließend ruft man diesen wie eine Methode auf:
Code: markieren
// C# Syntax
      if (EventTest != null)
            EventTest(this, new EventArgs());

Delphi-Quellcode: markieren
// Delphi Syntax
  if Assigned(FSingleSampleEventHandler) then
    FSingleSampleEventHandler(Self, EventArgs.Create);


Notiz meinerseits: "delegate" (englisch) wird im Deutschen i.A. mit "Delegate(n)" übersetzt und ist nichts weiter als ein schönes Wort für "statische Callback Funktionen"

 Zuletzt bearbeitet von sakura am 11.10.2004, 14:20, insgesamt 1-mal bearbeitet.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #5|Beitrag #248331Verfasst am: 11.10.2004, 14:51      Titel: Re: Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Attribute und der System.Attribute Typ


Attribute werden genutzt, um Typen und Typen-Members (z.B. Felder, Eigenschaften, Methoden) zu "dekorieren". Attribute werden als Metadaten innerhalb einer .NET Framework Anwendung (oder Assembly) gesichert. Zur Laufzeit kann man Typen, Typen-Members und Instanzen auf das Vorkommen solcher Attribute hin überprüfen.

Die generelle Syntax für Delphi und C# ist im Grunde gleich und kommt direkt vor dem Symbol, auf welches das Attribut angewandt wird:
Code: markieren
[AttributeTypeName(Parameter, Parameter)]
public class Foo { ... }


Hinweis: Es ist definiert, dass Attributnamen immer auf das Wort Attribute enden (z.B.: DesignerAttribute, ComVisibleAttribute). Die meisten Compiler erlauben es einem den Teil "Attribute" wegzulassen.

Was kann man nun mit diesen Attributen anfangen? Die meisten Entwicklungsumgebungen bieten spezielle Design-Time Klassen, welche es einem ermöglichen eine Komponente/ein Control in der Oberfläche (zur Designzeit) zu modifizieren. Dazu dient (in .NET) zum Beispiel das DesignerAttribute:
Code: markieren
[DesignerAttribute("MyControlDesigner")]
      public class MyControl : System.Windows.Forms.Control
      { … }

Wenn der WinForms Designer einen Designer für ein Control erstellt, stößt dieser auf das DesignerAttribute[i] der Klasse und erstellt einen [i]MyControllDesigner für diese.

Ein weiteres gutes Beispiel ist ComVisibleAttribute. Man kann .NET Assemblies dem COM Subsystem zur Verfügung stellen, indem man diese mit regasm.exe registriert. Jeder Typ, welcher mit ComVisibleAttribute markiert ist wird damit dem COM Subsystem zugänglich:
Code: markieren
[ComVisible(true)]
      public interface MyInterface
      {

      }

Man kann sich jetzt die Frage stellen, ob man jetzt jeden Typ so markieren muss, der dem COM Subsystem zur Verfügung gestellt werden soll. Die Antwort ist: nein. Man kann dieses Attribut auch dem gesamten Assembly zur Verfügung stellen:
Code: markieren
[assembly: ComVisible(true)]

Assembly-Level Attribute können auch für andere Dinge genutzt werden (z.B.: Version, Autor, Firmenname, etc.):
Code: markieren
[assembly: AssemblyTitle("This is my cool assembly")]
[assembly: AssemblyDescription("It does neat stuff")]
[assembly: AssemblyCompany("Borland Software Corporation")]
[assembly: AssemblyVersion("1.0.3.5")]


Attribute abfragen

Um Attribute für einen Typen oder eine Instanz zu ermitteln kann man sich der Reflection und des TypeDescriptor bedienen:
Delphi-Quellcode: markieren
var
  Attributes: AttributeCollection;
begin
  Attributes := TypeDescriptor.GetAttributes(Self);

Hinweis: Man kann eine Instanz (z.B: Self in Delphi oder this in C#) oder auch einen Sysmte.Type an TypeDescriptor.GetAttributes übergeben. Im Hintergrund wird immer auf den Typ zugegriffen, da Attribute Metadaten sind und diese im Typ, nicht in der Instanz, gesichert sind.

Nachdem man Zugriff auf die AttributeCollection erlangt hat, kann man diese recht einfach durchlaufen:
Delphi-Quellcode: markieren
for AnAttribute in Attributes do
  begin
    TextBox1.Text := TextBox1.Text + AnAttribute.ToString + #13#10;
  end;

Hinweis: Hier wurde die neuere "Delphi 9" for-Schleifen-Syntax genutzt. In Delphi 8 muss man den Iterator manuell erstellen und durchlaufen.

Wenn man nur auf ein bestimmtes Attribute zugreifen möchte, so kann man das wie folgend tun:
Delphi-Quellcode: markieren
var
  Attributes: AttributeCollection;
  DefaultEventAttr: DefaultEventAttribute;
begin
...
  DefaultEventAttr :=
      DefaultEventAttribute(Attributes[TypeOf(DefaultEventAttribute)]);
  if DefaultEventAttr <> nil then
    Text := 'Has a Default Event name of: ' + DefaultEventAttr.Name;

Man beachte, dass null zurückgeliefert wird, wenn der Typ keine Attribute besitzt.

Wenn man die Attribute eines bestimmten Mitgliedes (Type-Member) ermitteln möchte, muss man Reflection nutzen, um das Mitlgied zu finden. Anschließend kann man Attribute.GetCustomAttributes(..) nutzen, um auf die Attribute des Mitgliedes zuzugreifen:
Delphi-Quellcode: zusammenfalten | markieren
[TMyCustomMethodAttriute]
procedure TMainForm.Button1_Click(sender: System.Object; e: System.EventArgs);
var
  MyType: System.Type;
  ClickMethod: MethodInfo;
  MethodAttrs: array of Attribute;
  MethodAttr: Attribute;
  I: Integer;
begin
  { Use reflection to get the Button1_Click member}
  MyType := GetType;

  ClickMethod := MyType.GetMethod('Button1_Click', BindingFlags.NonPublic or BindingFlags.Instance);
  MethodAttrs := Attribute.GetCustomAttributes(ClickMethod);
  TextBox1.Text := '--- Method Attributes --- '#13#10;
  for I := 0 to Length(MethodAttrs) - 1 do
  begin
    MethodAttr := MethodAttrs[I];
    TextBox1.Text := TextBox1.Text + MethodAttr.ToString + #13#10;
  end;

Wenn man Attribute.GetCustomAttributes(..) nutzt, kann man einen zweiten Parameter übergeben, um auch die Vorgängertypen zu untersuchen. In diesem Beispiel würde es nichts ändern, da diese Methode keine Vorgänger hat.

Eigene Attribute

Es ist recht einfach eigene Attribute zu erstellen. Man muss nur wenige Dinge beachten. Am wichtigsten ist, das jedes Attribute direkt oder indirekt von System.Attribute abgeleitet werden muss:
Delphi-Quellcode: markieren
{ This can only be applied to methods }
  [AttributeUsage(AttributeTargets.Method)]
  TMyCustomMethodAttriute = class(Attribute)

  end;

Hinweis: Bachten Sie, dass das AttributeUsage Attribute dem neuen Attribute hinzugefügt wurde. Das teilt dem Compiler mit, dass dieses Attribute auch als solches genutzt werden darf.

 Zuletzt bearbeitet von sakura am 11.10.2004, 14:52, insgesamt 1-mal bearbeitet.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #6|Beitrag #248384Verfasst am: 11.10.2004, 15:37      Titel: Re: Einführung in die .NET Framework Klassen Bibliothek Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

System.Object


Es ist wichtig die Basisklasse aller Klassen zu nennen: System.Object. Delphi und C# leiten alle Klassen implizit von Object ab. Es gibt vier wichtige Methoden von Object welche genannt werden sollten: Equals, Finalize, GetHashCode und ToString.

System.Object.Equals(...)

The Methode Equals wird genutzt, um zwei Objekte miteinander zu vergleichen. Diese Methode kann überschrieben werden, wenn man feststellen will, ob zwei Objekte identisch sind. Die Standardimplementierung liefert true zurück, wenn die Referenzen zweier Objekte identisch sind. Anders ausgedrückt, Equals überprüft nicht, ob die Werte identisch sind. Ausnahme zu dieser Regel sind Wertetypen, diese werden als identisch betrachtet, wenn deren Bits identisch sind.

System.Object.GetHashCode(...)

GetHashCode wird immer aufgerufen, wenn ein Objekt in eine Hashtabelle eingefügt wird. Allgemein: wenn man GetHashCode überschreibt, dann sollte man auch immer Equals überschreiben, ansonsten kann es zu Problemen bei der Nutzung in Hashtabellen kommen.

GetHashCode sollte immer sehr performant sein und einen Integerwert zurückliefern, welcher das Objekt (fast) eindeutig identifizieren kann. Kommt es bei den HashCode-Werten zu Kollisionen, so wird Equals aufgerufen, um zwei Objekte miteinander zu vergleichen; das ist auch der Grund, warum Equals überschrieben werden sollte, wenn man GetHashCode überschreibt..

System.Object.Finalize(...)

Finalize ist der Basis-Destructor für Objekte. Finalize wird immer automatisch aufgerufen, wenn ein Objekt der Garbage-Collection hinzugefügt wird, außer man ruft explizit die Methode SurpressFinalize(...) auf. In Delphi wird Finalize durch Destroy, in C# durch ~ClassName definiert. Da jede Sprache bereits ihre eigene Art hat die Finalize Methode zu spezifizieren, erlauben diese es auch nicht Finalize zu überschreiben.

Es gibt einige wichtige Punkte, welche bei Finalize zu beachten sind. Erstens, man kann nicht vorhersagen wann die Methode aufgerufen wird. Wenn es wichtig ist, dass Resourcen wieder freigegeben werden, dann sollte man sich NIE auf Finalize/Destroy verlassen. Stattdessen sollte man die Schnittstelle IDisposable implementieren und die Resourcen in der Dispose(...) Methode freigeben. Jeder, der das Objekt dann einsetzt sollte Dispose aufrufen, um die Resourcen wieder freizugeben. Für den Fall, das es jemand vergessen sollte Dispose aufzurufen, sollte man Dispose auch aus Finalize heraus aufrufen. Es ist aber sicher zu stellen, dass Dispose nicht bereits ausgeführt wurde. Das sichert einen dagegen ab Resourcen ausversehen auf Dauer zu belegen.

System.Object.ToString(...)

Eine sehr praktische Methode aller Objekte ist ToString. Diese Methode ermöglicht es jedem Objekt sich als String zu repräsentieren. Es ist z.B. sehr praktisch, um Integerwerte als Strings darzustellen; einfach .ToString(...) ans Ende anfügen und schon hat man die Stringdarstellung eines Integers.

Für eigene Objekt kann es sinnvoll sein ToString zu überschreiben und damit eine gute Darstellung des Objektes als String zu erzielen.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #7|Beitrag #248393Verfasst am: 11.10.2004, 15:46      Titel: Re: [BorCon] Einführung in die .NET Framework Klassen Biblio Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

System.String und System.Text.StringBuilder


Es ist wichtig zu wissen, dass eine Instanz von System.String nie modifiziert werden kann. Das heißt, einmal erstellt, kann der enthaltene String nicht mehr geändert werden. Alle Anweisungen, welche den Anschein haben den String zu ändern erstellen im Hintergrund eine neue String-Instanz und liefern diese zurück. Während eine augenscheinlich einfache Anweisung wie:
Delphi-Quellcode: markieren
Foo := Foo + 'Another String';

auf den ersten Blick gut aussieht, so wird man in einer Schleife schnell feststellen, dass dem nicht so ist. Der Grund? Der String Foo muss mit jeder Änderung neu erstellt werden und das kann sehr langsam sein.

The Lösung ist denkbar einfach, man kann die Klasse System.Text.StringBuilder nutzen:
Delphi-Quellcode: zusammenfalten | markieren
var
  Attributes: AttributeCollection;
  AnAttribute: Attribute;
  DefaultEventAttr: DefaultEventAttribute;
  MyBuilder: StringBuilder;
begin
  { The above implementation of writing to the text box string is slow
    since strings are immutable (can't be changed) }

  { Instead of simply performing string concatenations,
    it is more performant to use a StringBuilder class }

  Attributes := TypeDescriptor.GetAttributes(Self);
  MyBuilder := StringBuilder.Create;
  MyBuilder.Append(' -- All Attributes on the Type ---'#13#10);
  for AnAttribute in Attributes do
  begin
    MyBuilder.Append(AnAttribute.ToString);
    MyBuilder.Append(#13#10);
  end;
  TextBox1.Text := MyBuilder.ToString;
end;

Hinweis: In diesem einfachen Beispiel wird man kaum Performanceunterschiede bemerken, aber in einer langen und engen Schleife wird man! Wenn man Zweifel hat, sollte man wahrscheinlich immer auf die Klasse System.Text.StringBuilder zurückgreifen.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #8|Beitrag #248424Verfasst am: 11.10.2004, 16:19      Titel: Re: [BorCon] Einführung in die .NET Framework Klassen Biblio Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Einige meiner Lieblingsklassen


System.Collections.ArrayList

Oft benötige ich eine liste von Objekten und die ArrayList ist geradezu perfekt für solche Situationen. Es gibt verschiedene Situationen, für welche ich die ArrayList nutze.

Oft kopiere ich zum Beispiel die Inhalt einer ArrayListe in ein Array Objekt:
Delphi-Quellcode: zusammenfalten | markieren
var
  MyList: ArrayList;
  MyStrs: array of string;
begin
  MyList := ArrayList.Create;

  MyList.Add('Hello');
  MyList.Add('World');
  MyList.Add('Foo');

  SetLength(MyStrs, MyList.Count);
  MyList.CopyTo(MyStrs);
end;


Der Vorteil dieser Methode ist, dass man den gesamten Inhalt der ArrayListe in einem typisierten Array hat. Man beachte, dass dieses Beispiel zur Laufzeit einen Ausnahmefehler erzeugen würden, wenn in der ArrayListe andere Werte als Strings enthalten sind. Desweiteren muss immer sicher gestellt sein, dass das Array groß genügend ist, um die Werte der ArrayListe aufzunehmen. In obigem Beispiel wird das durch den Aufruf zu SetLength sicher gestellt.

Ein weiterer wichtiger Punkt ist, das ein dynamisches Delphi-Array (hier: "array of string") und das System.Array des .NET Framework äquivalent sind.

Ich nutze die ArrayList auch desöfteren, um Elemente zu sortieren. Die Methode Sort[i] ist die Standardimplementierung, um diese Aufgabe zu erledigen und meist reicht diese auch aus. Sollte man jedoch Objekte haben, welche sich nicht einfach sortieren lassen, so kann man die Schnittstelle [i]IComparer implementieren und diese an ArrayList.Sort(IComparer) übergeben.

Die Implementierung ist einfach; es muss nur eine Methode Compare(...) zur Verfügung gestellt werden. Diese sollte einen Wert kleiner 0 zurückliefern, wenn das erste Objekt kleiner ist als das zweite Objekt, 0 wenn diese gleich sind und einen Wert größer als 0, wenn das erste Objekt größer ist als das zweite.

Die ArrayList[i] Klasse implementiert die [i]IList Schnittstelle, welche von IEnumerable abgeleitet ist. Jede Klasse, welche IEnumerable implementiert kann auch sehr einfach durchlaufen werden. Man muss sich nur merken, wie man dieses tut.
Code: markieren
// in C#
foreach (object foo in myArrayList) do
    // Do something with foo

Delphi-Quellcode: markieren
// in Delphi 9 (ähnlich, allerdings muss Foo deklariert werden)
var
  Foo: System.Object;
begin
...
  for Foo in MyArrayList do
    // Do something with Foo


System.Collections.Hashtable

Ich liebe Hashtabellen und nutze diese überall und immer wieder. Die Implementierung dieser durch die FCL ist so flexibel gehalten, dass auch Du diese bald genauso nutzen wirst.

Die Benutzung einer Hashtabelle ist sehr einfach:
Delphi-Quellcode: zusammenfalten | markieren
var
  MyHash: Hashtable;
  MyObj: System.Object;
  MyInt: Integer;
begin
  MyHash := Hashtable.Create;
  MyHash['Key1'] := Self;
  { Overwrite the value }
  MyHash['Key1'] := 1;
  { Access the value }
  MyObj := MyHash['Key1'];
  { We know it is an integer }
  if MyObj <> nil then
    MyInt := Integer(MyObj);
  { Set the value to nil; 'Key1' still exists in the hashtable }
  MyHash['Key1'] := nil;
  { Remove it from the hashtable }
  MyHash.Remove('Key1');
end;


Es gibt allerdings ein paar Dinge, welche berücksichtigt werden sollten. Erstens, wird ein Schlüssel/Wert auf nil gesetzt, so wird der Schlüssel nicht aus der Hashtabelle entfernt, dazu muss die Methode Remove(Schlüssel) aufgerufen werden. Will man alle Schlüssel/Werte-Paare durchlaufen, so kann man auf die Keys bzw. auf die Werteeigenschaften der Hashtabelle zugreifen:
Delphi-Quellcode: markieren
for Obj in MyHash.Keys do
    Console.Write(Obj.ToString);


Will man auf alle Schlüssel/Werte-Paare zugreifen, so muss man die Schnittstelle IDictionaryEnumerator manuell ansprechen:
Delphi-Quellcode: zusammenfalten | markieren
var
  MyHash: Hashtable;
  Enumerator: IDictionaryEnumerator;
begin
  MyHash := Hashtable.Create;
  ...
  Enumerator := MyHash.GetEnumerator;
  while Enumerator.MoveNext do
  begin
    Console.WriteLine('Key: ' + Enumerator.Key.ToString);
    Console.WriteLine('Value: ' + Enumerator.Value.ToString);
  end;
end;


System.Diagnostics

Oft will man sicherstellen, dass der geschriebene Code auch korrekt ist. Nutzt man den Namensraum System.Diagnostics kann man jederzeit auf die Klasse Debug und die statischen Variablen zugreifen um Asserts durchzuführen:

Delphi-Quellcode: markieren
Debug.Assert(foo = bar, 'Foo should be equal to bar');


Wird ein Assert ausgeführt, so kann man in einem Debugger leicht erkennen, warum ein Assert eine Meldung ausgibt. Ich nutze diese Debuggingmethode ständig und finde diese unentbehrlich.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #9|Beitrag #248428Verfasst am: 11.10.2004, 16:23      Titel: Re: [BorCon] Einführung in die .NET Framework Klassen Biblio Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Zu guter Letzt


Die FCL ist riesengroß. Ich könnte ein Buch schreiben, welche all die coolen Dinge beschreibt und was man mit ihnen tun kann. Vorläufig solltest Du das hier gezeigte nur als Spitze eine Eisberges betrachten.

Lade Dir den SourceCode herunter und schaue Dir einige der hier genannten Beispiele an.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
 
sakura #10|Beitrag #248432Verfasst am: 11.10.2004, 16:26      Titel: Re: [BorCon] Einführung in die .NET Framework Klassen Biblio Antworten mit Zitat
Super-Moderator
Alter: 33
Status: offline
Beiträge: 11.294
angemeldet: 10.06.2002
Wohnort: München
RAD-Studio 2007 Architect

Corbin, der diesen Artikel im Original verfasst hat, hat dazu auch, wie oben übersetzt, Source Codes geschrieben. Jetzt kommt aber der Hammer: er hat diese noch nicht auf der Borland CodeCentral veröffentlicht. Jedoch dürfen wir diese hier Euch schon vorab zum Download anbieten.

Sobald er seine Code aus der Borland CodeCentral veröffentlicht hat, werden wir dorthin verlinken und die Kopie hier entfernen.

So, nun ist es auch schon soweit: Hier findet Ihr den Source Code

Viel Spass,
Euer sakura

...Cat...

Jeder Mensch lebt praktisch in seiner eigenen, privaten Welt. Kommunikation bedeutet zwischen diesen Welten Brücken zu bauen.
CodeGear Associate Evangelist

 Zuletzt bearbeitet von sakura am 11.10.2004, 19:13, insgesamt 1-mal bearbeitet.
nach oben nach unten
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen im Forum zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Google zu suchen. Markiere Begriffe im Text und klicke auf diesen Button, um nach zusätzlichen Informationen bei Wikipedia zu suchen.
 
Anzeige-Optionen:    
 
Delphi-PRAXiS Forum - Übersicht -> Tutorials und Kurse Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1   [ 10 Beiträge ]  
 
  Neuen Beitrag schreiben Dieses Thema ist gesperrt, Du kannst keine Beiträge editieren oder beantworten.
als PDF-Datei herunterladenThema ausdrucken
 
   
Gehe zu:  
Du darfst keine Beiträge in dieses Forum schreiben.
Du darfst auf Beiträge in diesem Forum nicht antworten.
Du darfst Deine Beiträge in diesem Forum nicht bearbeiten.
Du darfst Deine Beiträge in diesem Forum nicht löschen.
Du darfst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten.
Du kannst Dateien in diesem Forum nicht herunterladen.


Impressum / Kontakt
Allgemeine Geschäftsbedingungen
Verhaltenskodex & FAQ

Delphi-PRAXiS :: Das Forum für Delphi-Programmierer
Das Experten Forum für Delphi ProgrammiererHilfe für Borland Delphi gibts es hier im ForumDelphi Quelltexte und Source CodesDelphi-PRAXiS :: Das Forum für DelphiWindows APIInternet und NetzwerkeVCL und Datenbanken
 

Delphi-PRAXiS V.2005 III
© 2002-2010 by Daniel R. Wolf
powered by phpBB © phpBB Group

Impressum / Kontakt Allgemeine Geschäftsbedingungen