Info's zu Interface (XML-Datenbindung)
-
Hallo erstmal
Ich hab nur ein Verständnisproblem, da ich Code habe der funktioniert aber ich nicht so richtig begreif wie?
Ich habe mit dem XML-Datenbindung - Experten (Datei/Neu/weitere...) aus einer DTD eine Unit mit mehreren Interfaces und Klassen generiert. Es werden mehrere Schnittstellen / Interfaces erzeugt und wiederum Klassen die von diesen Interfaces abgeleitet sind.
class TXMLScrollDiaConf : public TXMLNode, public IXMLScrollDiaConf
In den Klassen werden allerdings Funktionen verwedet die Objekte zurückgegeben die irgendetwas mit DelphiInterface (_di_I) zu tun haben
virtual _di_IXMLDrawingCursor __fastcall GetDRAWINGCURSOR();
Der Zugriff wiederum erfolgt nun nur über diesen Rückgabetyp.
_di_IXMLScrollDiaConf confScrollDia = LoadScrollDiaConf(L"ScrollDiaConf.xml"); _di_IXMLDrawingCursor confDrawingCursor = confScrollDia->GetDRAWINGCURSOR();
Was ich nun wissen möchte ist warum brauch ich ein Interface und eine Klasse um auf eine XML-Datei zuzugreifen ?
Und, woraus ergeben sich diese Rückgabetypen (_di_I)? Und wieso kann ich nichtt direkt die Klasse bzw. das Interface verwenden ?Wenn jemand mehr Erfahrungen damit besitzt und eine Antwort auf diese Fragen hätte wäre ich sehr dankbar.
Hier noch die DTD
<!ELEMENT SCROLLDIACONF (DRAWINGCURSOR,DRAWINGAREA, SIGNALAXIS+, SIGNAL*)> <!ELEMENT DRAWINGCURSOR (timepos, graphicpos)> <!ELEMENT DRAWINGAREA (signallist, signallisttime, cursortime, maingrid, subgrid)> <!ELEMENT SIGNALAXIS (id, name, max, min, active)> <!ELEMENT SIGNAL (id, name, color, width, style, axis)> <!ELEMENT id (#PCDATA)> <!ELEMENT name (#PCDATA)> <!ELEMENT max (#PCDATA)> <!ELEMENT min (#PCDATA)> <!ELEMENT active (#PCDATA)> <!ELEMENT color (#PCDATA)> <!ELEMENT width (#PCDATA)> <!ELEMENT style (#PCDATA)> <!ELEMENT axis (#PCDATA)> <!ELEMENT signallist (#PCDATA)> <!ELEMENT signallisttime (#PCDATA)> <!ELEMENT cursortime (#PCDATA)> <!ELEMENT maingrid (#PCDATA)> <!ELEMENT subgrid (#PCDATA)> <!ELEMENT timepos (#PCDATA)> <!ELEMENT graphicpos (#PCDATA)>
und der Teile des generierte h-Code :
//--------------------------------------------------------------------- #ifndef ScrollDiaConfH #define ScrollDiaConfH //--------------------------------------------------------------------- #include <System.hpp> #include <xmldom.hpp> #include <XMLDoc.hpp> #include <XMLIntf.hpp> #include <XMLNodeImp.h> //--------------------------------------------------------------------- //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++ INTERVACE ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++ Forward-Dekl. __interface IXMLScrollDiaConf; typedef System::DelphiInterface<IXMLScrollDiaConf> _di_IXMLScrollDiaConf; __interface IXMLDrawingCursor; typedef System::DelphiInterface<IXMLDrawingCursor> _di_IXMLDrawingCursor; __interface IXMLDrawingArea; typedef System::DelphiInterface<IXMLDrawingArea> _di_IXMLDrawingArea; __interface IXMLSignalAxis; typedef System::DelphiInterface<IXMLSignalAxis> _di_IXMLSignalAxis; __interface IXMLSignalAxisList; typedef System::DelphiInterface<IXMLSignalAxisList> _di_IXMLSignalAxisList; __interface IXMLSignal; typedef System::DelphiInterface<IXMLSignal> _di_IXMLSignal; __interface IXMLSignalList; typedef System::DelphiInterface<IXMLSignalList> _di_IXMLSignalList; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++ IXMLScrollDiaConf //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ __interface INTERFACE_UUID("{5F2B5626-C1EE-4A2B-8C43-B6EB6D13823D}") IXMLScrollDiaConf : public IXMLNode { public: // Methoden für Zugriff auf Eigenschaften virtual _di_IXMLDrawingCursor __fastcall GetDRAWINGCURSOR() = 0; virtual _di_IXMLDrawingArea __fastcall GetDRAWINGAREA() = 0; virtual _di_IXMLSignalAxisList __fastcall GetSIGNALAXIS() = 0; virtual _di_IXMLSignalList __fastcall GetSIGNAL() = 0; // Methoden & Eigenschaften __property _di_IXMLDrawingCursor DRAWINGCURSOR = { read=GetDRAWINGCURSOR }; __property _di_IXMLDrawingArea DRAWINGAREA = { read=GetDRAWINGAREA }; __property _di_IXMLSignalAxisList SIGNALAXIS = { read=GetSIGNALAXIS }; __property _di_IXMLSignalList SIGNAL = { read=GetSIGNAL }; }; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //++ IXMLDrawingCursor //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ __interface INTERFACE_UUID("{1BE6ACB5-0448-4AC0-82C1-A161A9A33E0B}") IXMLDrawingCursor : public IXMLNode { public: // Methoden für Zugriff auf Eigenschaften virtual double __fastcall Gettimepos() = 0; virtual int __fastcall Getgraphicpos() = 0; virtual void __fastcall Settimepos(double Value) = 0; virtual void __fastcall Setgraphicpos(int Value) = 0; // Methoden & Eigenschaften __property double timepos = { read=Gettimepos, write=Settimepos }; __property int graphicpos = { read=Getgraphicpos, write=Setgraphicpos }; }; //.. //... //.... //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //********************************************************************* //**CLASS************************************************************** //********************************************************************* //** Forward-Dekl. class TXMLScrollDiaConf; class TXMLDrawingCursor; class TXMLDrawingArea; class TXMLSignalAxis; class TXMLSignalAxisList; class TXMLSignal; class TXMLSignalList; //********************************************************************* //** CLASS TXMLSCROLLDIACONF //********************************************************************* class TXMLScrollDiaConf : public TXMLNode, public IXMLScrollDiaConf { __IXMLNODE_IMPL__ private: _di_IXMLSignalAxisList FSIGNALAXIS; _di_IXMLSignalList FSIGNAL; protected: // IXMLScrollDiaConf virtual _di_IXMLDrawingCursor __fastcall GetDRAWINGCURSOR(); virtual _di_IXMLDrawingArea __fastcall GetDRAWINGAREA(); virtual _di_IXMLSignalAxisList __fastcall GetSIGNALAXIS(); virtual _di_IXMLSignalList __fastcall GetSIGNAL(); public: virtual void __fastcall AfterConstruction(void); }; //********************************************************************* //** CLASS TXMLDRAWINGCURSOR //********************************************************************* class TXMLDrawingCursor : public TXMLNode, public IXMLDrawingCursor { __IXMLNODE_IMPL__ protected: // IXMLDrawingCursor virtual double __fastcall Gettimepos(); virtual int __fastcall Getgraphicpos(); virtual void __fastcall Settimepos(double Value); virtual void __fastcall Setgraphicpos(int Value); }; //.. //... //.... //********************************************************************* //##################################################################### //## Globale Funktionen //##################################################################### _di_IXMLScrollDiaConf __fastcall GetScrollDiaConf(_di_IXMLDocument Doc); _di_IXMLScrollDiaConf __fastcall GetScrollDiaConf(TXMLDocument *Doc); _di_IXMLScrollDiaConf __fastcall LoadScrollDiaConf(const WideString FileName); _di_IXMLScrollDiaConf __fastcall NewScrollDiaConf(); //--------------------------------------------------------------------- #endif
-
Was ich nun wissen möchte ist warum brauch ich ein Interface und eine Klasse um auf eine XML-Datei zuzugreifen ?
Ein guter Verwendungszweck für XML ist die Sprach- bzw. Plattformunabhängige Kommunikation. Im wesentlichen gibt es drei (etablierte) Frameworks um dieses zu realisieren.
1. CORBA - Kommunikation direkt über Objekte duch Transformierung, welche von einer IDE- Datei gesteuert wird
2. COM/DCOM - Kommunikation über die Microsoft-COM-Dienste
3. Soap - Kommunikation über eine XML- Datei welche hin und her geschoben wird.Wenn du nun eine Komunikation über Soap anstrebst und die Daten einer Klasse verschicken möchtest wäre es doch toll, wenn es eine XML- Datei gäbe, die genau diese Daten der Klasse aufnehmen kann. Man erstellt also eine entsprechende DTD datei und erzeugt somit eine abstrakte Klasse welche du Programmintern verwenden kannst. Du erzeugst also die Klasse nicht selbst sonder lässt diese erzeugen. Genauso kann man dann zum Beispiel das in ein Java programm unter Linux machen. Man benutzt einfach die selbe DTD-Datei um eine eqivaliente Klasse zu erzeugen. So, nun kann die Kommunikation über die XML- Datei stattfinden.
Und, woraus ergeben sich diese Rückgabetypen (_di_I)? Und wieso kann ich nichtt direkt die Klasse bzw. das Interface verwenden ?
Die Implementierung der Schnittstellen fand in Objekt-Pascal statt.
Beispiel für das XMLNode:
template <class T> class RTL_DELPHIRETURN DelphiInterface; typedef System::DelphiInterface< IXMLNode > _di_IXMLNode;
Wobei DelphiInterface eine Object-Pascal-Schnittstelle in form einer Klasse (Interface) darstellt.
Interfaceklassen zu Delphi werden wie zum Beispiel _di_IUnknown (die Basisklasse) mit "_di_" gekennzeichnet. "IUnknown" ist also der Klassenmane in Delphi.Und wieso kann ich nichtt direkt die Klasse bzw. das Interface verwenden
Durch abstrakte Klassen bleibt die grundlegene Struktur gesichert. Es könnte später verschiedene Implementierungen von Klassen geben können. Damit dieses Klassen wieder zueinander finden können, müssen diese Klassen einen gemeinsamen Vorfahren haben. In diesen Fall wäre die gemeinsamme Klasse diese Abstrakte Klasse. Das ist auch eines der Gründe, weshalb man abstrakte Klassen verwenden soll. Zum Beispiel is TObjekt eine abstrakte Klasse. Diese Klasse taucht aber über all in den Programmen auf, wie jeder weiss.
-
Hi AndreasW
Danke für deine Antwort. Mir ist nun klar wozu Interfaces verwendet werden. Ich habe allerdings noch nicht die Beziehungen der einzelnen Klassen begriffen.
__interface IXMLDrawingCursor; typedef System::DelphiInterface<IXMLDrawingCursor> _di_IXMLDrawingCursor;
Die Zeile weist einfach dem DelphiInterface (_di_IXMLDrawingCursor) einen andern Bezeichner zu (IXMLDrawingCursor).
Grob gesagt _di_IXMLDrawingCursor = IXMLDrawingCursor.
Also _di_IXMLDrawingCursor ist das DelphiInterface, welches vom Compiler aus
IXMLDrawingCursor der Object-Pascal-Schnittstelle erzeugt wird.korrigier mich bitte, wenn ich irre
class TXMLDRAWINGCURSORType : public TXMLNode, public IXMLDrawingCursor
Die Zeile wiederum sagt: TXMLDRAWINGCURSORType ergibt sich nun aus der Funktionalität von TXMLNode und überschreibt die Funktionen von IXMLDrawingCursor (die ja nur rein virtual Funktionen enthält).
Somit ist TXMLDRAWINGCURSORType = TXMLNode + IXMLDrawingCursor und
IXMLDrawingCursor = _di_IXMLDrawingCursorNach meinem Verständnis ist IXMLDrawingCursor einfach eine Basisklasse(wie TObject) und TXMLDRAWINGCURSORType die spezialisierte Variante.
Warum muss ich dann im Programm _di_IXMLDrawingCursor verwenden um auf Funktionen zuzugreifen? Ich versteh das einfach nicht!
Irgendwo habe ich da einen Denkfehler nur ich finde ihn nicht.
Vielleicht hast du ja noch einen Gedanken.Nochmals Danke das du dir Zeit genommen hast zum beantworten
-
Hi,
Grob gesagt _di_IXMLDrawingCursor = IXMLDrawingCursor.
naja, nicht ganz. IXMLDrawingCursor ist die Schnittstellenklasse und _di_IXMLDrawingCursor die Schnittstelle. Ist schon was anderes.
System::DelphiInterface<IXMLDrawingCursor>
erzeugt eine Schnittstelle zu einer Klasse oder einer COM-Schnittstelle.
Dieses:
class TXMLDRAWINGCURSORType : public TXMLNode, public IXMLDrawingCursor
kan nalso nciht in Pascal übersetzt werden. Stattdessen werden Die Vorfahren als "Interfaces" intern deklariert.
Warum muss ich dann im Programm _di_IXMLDrawingCursor verwenden um auf Funktionen zuzugreifen? Ich versteh das einfach nicht!
Dieses Interface-Gehampel wird erzeugt, weil Objekt-Pascal keine Mehrfachvererbung unterstützt. Prinzipiel ist dieses in C++ nicht notwendig.
Der BCB muss allgemeingültigen Code (oder Kot) aus der DTD erzeugen. Die Klassen müssen später auch aus den Daten wiederum eine gültige XML-Datei erzeugen. Dieses macht der BCB in Object-Pascal.
Der BCB erzeugt also die Klassen so, weil es in dieser Form zu Objekt-Pascal kompatibel bleibt und weil irgend jemand meinte dass es so schön ist
-
Ok Vielen Dank
jetzt hab ichs geraftWußte nur noch nicht, dass man auch einen Unterschied zwischen Schnittstelle und Schnittstellenklasse machen kann und das mit der Kompatibilität zu Object Pascal war auch neu.
Jetzt weiß ich wenigstens wozu das alles da ist, falls mich mal jemand fragt was das soll.
Danke das du dir die Mühe gemacht hast.