AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Delphi Namespaces in Delphi 2005
Tutorial durchsuchen
Ansicht
Themen-Optionen

Namespaces in Delphi 2005

Ein Tutorial von sakura · begonnen am 6. Dez 2004 · letzter Beitrag vom 6. Dez 2004
Tutorial geschlossen
Benutzerbild von sakura
sakura
Registriert seit: 10. Jun 2002
Dieses Tutorial ist im Original von Marc Rohloff am 3. Dezember 2004 auf dem Borland Developer Network erschienen: Namespaces in Delphi 2005. Mit seiner freundlichen Genehmigung veröffentlichen wir hier die deutsche Version.

......
Ich bin nicht zurück, ich tue nur so
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#2
  Alt 6. Dez 2004, 09:28
Damit Delphi Assemblies zukünftig angenehmer in anderen .NET Sprachen angesprochen werden können, hat Borland sich entschieden in Delphi 2005 einen neuen Weg zu gehen, wie Namespaces implementiert werden. Das macht es vor allem für C# und VB.NET Programmierer einfacher. Das angenehme daran ist, dass Borland dieses geschafft hat ohne die Sprache zu ändern und ohne die Rückwärtskompatibilität zu Delphi 8 für .NET zu gefährden. Eigentlich muss man sich nicht einmal groß darum sorgen wie Namespaces in Delphi implementiert werden.

Zusammenfassung
  • Namespaces haben keinen Einfluss in Win32 Entwicklungen
  • Namespaces orientieren sich am Namen der Unit wie folgend:
    • Wenn ein Unitnamen Punkte enthält, so wird der Unitnamen bis zum letzten Punkt genutzt.
    • Hat der Unitnamen keine Punkte, so wird der Default-Namespace genutzt
    • Gibt es keinen Default-Namespace, so wird der Unitnamen genutzt
  • Code, der aus Delphi 8 übernommen wird benötigt evtl. einige Anpassungen
  • Man sollte immer Packages, nicht Libraries, nutzen um nutzbare Assemblies zu erstellen
  • Delphi spricht Typen immer über deren vollständigen Unitnamen an
  • Andere .NET-Sprachen sprechen die Typen immer über deren Namespaces an
  • ASP.NET Deklerationen, Konfigurationsdateien und .NET Reflektion sprechen Typen immer über deren Namespaces an
  • Sollten mehrere Units innerhalb eines Namespaces Typen mit gleichen Namen veröffentlichen, dann kann das Assembly unbrauchbar sein.

Da Namespaces ein spezielles .NET Feature sind, trifft dieser Artikel nur die Delphi.NET Personalität. Für Delphi Win32 Anwendungen ergeben sich keine Neuerungen oder Änderungen.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#3
  Alt 6. Dez 2004, 09:47
Namespaces in Delphi 8


Zuerst möchte ich noch einmal darauf eingehen, wie Delphi 8 mit Namespaces umgegangen ist. Hierzu möchte ich zwei einfache Source-Dateien nutzen:
Delphi-Quellcode:
unit Sample.Controls.Base;

interface

type
  TControl = class
  end;

implementation

end.
Delphi-Quellcode:
unit Sample.Controls.Listview;

interface

type
  TListview = class(TControl)
  end;

type
  TItem = class
  end;

implementation

end.
Wen man diese Dateien in Delphi 8 in ein Package kompiliert und sich das Ergebnis mit Hilfe eines Reflektor-Tools betrachtet, so stellt man fest, dass das Package zwei Namespaces enthält: Sample.Controls.Base und Sample.Controls.Listview.

Öffnet man jetzt den Namespace Sample.Controls.Base, so sieht man, dass dieser zwei Klassen enthält. Die eine ist unsere TControl Klasse, die andere heißt Unit. Diese zweite, spezielle Klasse enthält den Initialisierungs- und Finalisierungscode der Sample.Controls.Base Unit, sowie alle Funktionen und Prozeduren, welche auf Unit-Level deklariert/implementiert wurden. Entsprechend sind im Namespace Sample.Controls.Listview die Klassen TListview und TItem sowie die spezielle Klasse Unit enthalten.

Wen man jetzt weitere Units dem Package hinzufügt, so wird man feststellen, dass jede Unit ihren eigenen, eindeutigen Namespace mit allen Klassen sowie der Klasse Unit dem Package hinzufügt.

So, wo ist jetzt das Problem?

Units sind viel einfacher zu benutzen und zu verwalten wenn diese jeweils nur wenige Klassen enthalten. Wie dem auch sei, erstellt man Libraries/Packages mit vielen Units, so sind in den Assemblies entsprechend viele Namespaces enthalten. Das stört uns als Delphientwickler nicht weiter, da der Compiler sich um diese interna sorgt. Allerdings ist dieser Mechanismus für Entwickler, welche andere .NET Sprachen nutzen, sehr umständlich. C# Programmierer müssen so z.B. jeden Namespaces separat importieren was deren Code nur unnötig aufbläht. Auch hat es den Nachteil, dass Delphi.NET Assemblies für Programmierer anderer .NET Sprachen schwerer zu verstehen sind. Wollen/müssen diese den vollständigen Typennamen nutzen, so müssen sie jedes Mal etwas wie das folgende tippen: Sample*.Con*trols*.Base*.TControl oder Sample.Con*trols.Listview.TListview.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#4
  Alt 6. Dez 2004, 10:04
Namespaces in Delphi 2005


Lädt man jetzt das zuvor in Delphi 8 erstellte Package und kompiliert es erneut und schaut sich das Ergebnis in einem Reflektor-Tool an, so wird man feststellen, dass das erstellte Assembly etwas anders strukturiert ist. Es enthält jetzt zwei Namespaces: Sample.Controls und Sample.Controls.Units.

Wenn man den Sample.Controls Namespace näher betrachtet, so findet man dort die Klassen TControl, TListview und TItem. Der Delphi 2005 Compiler hat allen Klassen in einen Namespace platziert!

Der Sample.Controls.Units Namespace ist entsprechend ähnlich aufgebaut und enthält nun zwei Klassen: Base und Listview. Dieses sind die speziellen Klassen jeder Unit, welche wir vorher auch bereits hatten. Im Unterschied zu Delphi 8 wird jetzt nicht mehr für jede Unit ein eigener Namespace erzeugt.

Dieses ist eine großer Erleichterung für andere Entwickler. C# Programmierer benötigen jetzt nur noch ein using Statement, um Zugriff auf alle unsere Klassen zu erhalten. Um jetzt Zugriff auf eine unserer Klassen zu erhalten, reicht folgender Code: Sample.*Controls.*TCon*trol.

Fügt man jetzt dem Package diese dritte Unit hinzu:
Delphi-Quellcode:
unit Sample.Graphics.Screen;

interface

type
  TScreen = class
  end;

implementation

end.
so wird man feststellen, dass das Package jetzt zwei neue Namespaces Sample.Graphics namespace und Sample.Graphics.Units enthält.

Wo kommt diese jetzt her?

Der Delphi Compiler betrachtet jeden Unitnamen genauer. Sind in dem Unitnamen Punkte (.) enthalten, so wird alles, was links vom letzten Punkt steht als Teil des zu generierenden Namespace genutzt. Anders gesagt, wenn eine Unit Sample.Controls.Buttons benannt wird, so werden die darin enthaltenen Klassen in den Namespace Sample.Controls gebracht, heißt eine Unit Sample.*Controls.*Web.*DB.Grid, so werden alle darin enthaltenen Klassen in den Namespace Sample.*Controls.*Web.*DB gebracht.

Für Unitnamen, die keinen Punkt im Namen enthalten, nutzt der Compiler den Standard Namespace aus dem Dialog Projektoptionen:

Wurde in diesem Dialog kein Standard Namespace angegeben, so nutzt der Compiler den Namen der Unit als Namespace. Daher wird eine Unit mit dem Namen Graphics.pas dann auch einen Namespace Graphics erstellen.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#5
  Alt 6. Dez 2004, 10:33
Einige wichtige Dinge, die man beachten sollte


Wie bei allen Veränderungen, gibt es auch hier ein paar Fettnäpfchen, auf welche man achten sollte. Drei Punkte die man beachten und überprüfen sollte, wenn man auf seltsame Fehler stößt.

Benutze immer Packages

Borland hat immer empfohlen nicht die Library Projekte zu nutzen, um Assemblies zu erstellen. In Delphi 2005 ist der Compiler dahingehend strikter und erlaubt es einem nicht mehr Anwendungen zu erstellen, welche auf eine Delphi-Library verweisen.

Man sollte daher immer Packages nutzen, um .NET Assemblies zu erstellen.

Typen immer über den vollständigen Bezeichner ansprechen

Die meisten .NET Sprachen verlangen von einem den Namespace zu benutzen, um Typen eindeutig zu identifizieren oder wenn man Namespaces importiert (z.B. using). Delphi wird jedoch immer den Unitnamen nutzen und niemals den Namespace, um einen Typen zu nutzen. Diese Regel hält auch stand, wenn man ein Delphi-Package eines anderen Herstellers nutzt. Delphi erkennt diese und nutzt die entsprechenden Unitnamen.

Hinweis: nutzt man Assemblies, welche in anderen Sprachen erstellt wurden, so nutzt man einfach den Namespace, um die Typen zu nutzen.

Dieser Unterschied ist häufig verwirrend. Ein einfaches Beispiel ist der Gebrauch von TypeConverters und Designers. Zum Bespiel: ein Typenkonvertierer in einer Delphi Unit:
Delphi-Quellcode:
unit Sample.Controls.Design;

Type
  TConverter = class(TypeConverter)
  end;
Um diesen zu nutzen nutzt man den vollständigen Namen:
Delphi-Quellcode:
Uses
  Sample.Controls.Design;

type
  [TypeConverter(typeof(TConverter))]
  TItem = class
  end;
oder
Delphi-Quellcode:
Type
  [TypeConverter(typeof(Sample.Controls.Design.TConverter))]
  TItem = class
  end;
In C# hingegen nutzt man einfach nur den Namespace:
Code:
[b]using[/b] Sample.Controls;

[TypeConverter([b]typeof[/b](TConverter))]
[b]class[/b] TListItem {
}
bzw.
Code:
[TypeConverter([b]typeof[/b](Sample.Controls.TConverter))]
[b]class[/b] TListItem {
}
Wie dem auch sei, zu jeder Regel gibt es mindestens eine Ausnahme. Auch in Delphi gibt es verschiedene Situationen in welchen man die Namespaces nutzt.

Ein Beispiel ist die Erstellung von ASPX, ASCX und ASMX Dateien. Erstellt man zum Beispiel eine Webseite mit dem Namen TWebForm in der Datei Application.*Pages.*WebForm1.**pas, dann sieht das PAGE-Tag wie folgend aus:
Code:
[color=#b600ff]<%@Page Language="c#" Codebehind="WebForm1.pas" Inherits="Application.Pages.TWebForm1"%>[/color]
Ein anderer Fall ist es, wenn man Informationen zu .NET durch Strings weiterleiten will, speziell zum Beispiel, wenn man Reflektionen nutzt:
Delphi-Quellcode:
var c: TypeConverter;
[...}
  c := Assembly.CreateInstance('Sample.Controls.TConverter');
Dieser feine Unterschied führt häufig zu Fehlern und Problemen und muss genauestens berücksichtigt werden, wenn man Code aus Delphi 8 importiert oder aus anderen Sprachen konvertiert.

Doppelte Typen

Nutzt man den gleichen Typenamen in zwei verschiedenen Units, welche in einem Namespace kompiliert werden, so werden zwei Klassen mit der gleichen Bezeichnung generiert. Zum Beispiel: fügt man folgende Unit zu dem oben erstellten Package hinzu:
Delphi-Quellcode:
unit Sample.Controls.Treeview;

interface

type
  TTreeview = class(TControl)
  end;

type
  TItem = class
  end;

implementation

end.
Nun hat man zwei Klassen im Package, welche den Namen TItem tragen. Eine wurde in Sample.Controls.*List*view.*pas deklariert, die zweite in Sample.Controls.*Treeview.pas. Nutzt man jetzt wieder ein Reflektor-Tool, so wird man feststellen, dass sich im Namespace Sample.Controls zwei Klassen mit dem Namen TItem befinden. Das kann nicht nur bei Klassentypen, sondern bei allen von Delphi unterstützen Typen (z.B. Records und Enumerationen) geschehen.

Um dieses Problem zu umgehen benennt der Compiler alle Typen um, welche nicht ausserhalb des Assemblies sichtbar sind, anders gesagt, alles was nach dem Keyword implementation definiert wird. Delphi erreicht das, indem der Unitnamen an alle Typenbezeichner angehangen wird.

Wie dem auch sei, gibt es zwei öffentliche Typen mit dem gleichen Namen im gleichen Namespace, so ändert Delphi nichts. Entwickler, welche andere Tools (z.B. C#) nutzen, können hier auf Probleme stoßen. Eine zukünftige Version des Delphi Compilers sollte solche Probleme erkennen und entsprechend handeln. Bis dahin empfehle ich eine Tool wie z.B. peverify aus dem .NET SDK zu nutzen, um solche Eventualitäten aufzudecken.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#6
  Alt 6. Dez 2004, 10:38
Code von Delphi 8 nach Delphi 2005 portieren


Normalerweise sollte es keine Probleme geben, wenn man Code aus Delphi 8 nach Delphi 2005 portiert. Man sollte jedoch obige Punkte immer bedenken.

Folgende Punkte sollten nach Bedarf überprüft werden:
  • Libraries sollten in Packages umgewandelt werden, ausser man nutzt unmanaged Code
  • Man sollte Namespaces, welche man im Code genutzt hat, überprüfen
  • Die IDE sollte ASPX-Tags automatisch konvertieren, aber eine Kontrolle schadet nicht
  • Man sollte seine Assemblies immer mit Hilfe eine Tools wie peverify auf doppelte Typenbezeichner überprüfen
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#7
  Alt 6. Dez 2004, 10:43
Zusammenfassung


Wenn man verstanden hat, wie Delphi 2005 Namespaces erstellt, so wird man feststellen, dass Delphis Namespace-Unterstützung logisch, flexibel und sehr einfach zu nutzen ist, ohne dabei die Sprache selbst zu ändern. Es ist so einfach, dass man es nicht einmal feststellt, bis man darauf angewiesen ist. Um so mehr, als dass es einfacher wird Delphi.NET Assemblies in anderen Sprachen zu nutzen.

Es ist lediglich wichtig sich zu merken, dass Namespaces und Unitnamen nicht länger ein und das selbe sind und Delphi immer die Unitnamen nutzt.
Daniel W.
 
Benutzerbild von sakura
sakura

 
Delphi 11 Alexandria
 
#8
  Alt 6. Dez 2004, 10:48
Hi DPler,

auch dieses Thread werde ich wieder sperren, da Marc Rohloff hier keine Kommentare zu den Inhalten abgeben kann. Wer inhaltliche Übersetzungsfehler findet, sende mir bitte eine kurze PM und nenne diese

Wer sonstige Fragen zu diesem Thema hat, der frage bitte im Forum oder lese noch einmal das Original. Da ist auch eine Kontaktadresse genannt, um mit Marc direkt über dieses Thema zu diskutieren.

Über Marc Rohloff
Marc Rohloff beschäftigt sich fast ausschließlich mit all dem, was zur IT Bezug hat. Momentan spezialisiert er sich auf .NET Technologien und ist Mitglied des TeamB. Er hat an vielen Plätzen der Welt gearbeitet, momentan ist er in Columbus, Ohio, USA als freier Delphi-Lehrer. Marc kann über Email erreicht werden: marc2005@bigfoot.com (in Englisch bitte)


......
Daniel W.
 
Tutorial geschlossen


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz