Selbst die Inspektion von VB6 UDTs
Habe ich das Gefühl, die Antwort auf das wird "nicht möglich", aber ich werde give it a shot...
Ich bin in der wenig beneidenswerten position geändert wird, ein Vermächtnis VB6-app mit einigen Verbesserungen. Umstellung auf eine intelligentere Sprache ist nicht eine option.
Die app setzt auf eine große Sammlung von benutzerdefinierten Typen um Daten zu verschieben. Ich möchte definieren, die eine gemeinsame Funktion, die Sie treffen können einen Verweis auf eine dieser Arten, und extrahieren Sie die enthaltenen Daten.
In pseudo-code, hier ist, was ich Suche:
Public Sub PrintUDT ( vData As Variant )
for each vDataMember in vData
print vDataMember.Name & ": " & vDataMember.value
next vDataMember
End Sub
Scheint es, wie das info verfügbar sein muss, um COM-irgendwo... Keine VB6-gurus da draußen care, take a shot?
Dank,
Dan
Oops sorry. Ich merkte es nach der Buchung, dass der name der Funktion ist PrintUDT. Also, es sollte ein Typ sein (so eine Art struct). Richtig?
Verwandte: stackoverflow.com/questions/3222080/...
InformationsquelleAutor Dan | 2009-02-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
Im Gegensatz zu dem, was andere gesagt haben, IST es möglich die run-time-type-information für UDT in VB6 (es ist zwar nicht ein built-in-Sprache-Funktion). Microsoft TypeLib-Informationen Objekt-Bibliothek (tlbinf32.dll) können Sie programmgesteuert prüfen COM-Typ-Informationen zur Laufzeit. Sollten Sie bereits über diese Komponente, wenn Sie Visual Studio installiert haben: zum hinzufügen zu einer vorhandenen VB6-Projekt, gehen Sie zu Projekt->Referenzen und überprüfen Sie den Eintrag mit der Bezeichnung "TypeLib-Informationen." Beachten Sie, dass Sie haben, zu verteilen und registrieren tlbinf32.dll im setup-Programm der Anwendung.
Können Sie überprüfen UDT-Instanzen mit Hilfe der TypeLib-Informationen-Komponente zur Laufzeit, wie lange Ihre UDT deklariert sind
Public
und definiert, innerhalb einerPublic
Klasse. Dies ist notwendig, damit der VB6 erzeugen von COM-kompatibler Typ-Informationen für Ihre UDT ' s (die dann aufgezählt werden, mit verschiedenen Klassen in der TypeLib-Informationen-Komponente). Der einfachste Weg, um diese Anforderung zu erfüllen wäre, um alle Ihre UDT ' s in einem öffentlichenUserTypes
Klasse, die kompiliert wird in einer ActiveX-DLL oder ActiveX-EXE.Zusammenfassung ein Beispiel
Diesem Beispiel enthält drei Teile:
PrintUDT
Methode zu demonstrieren, wie Sie aufzählen können, die Felder einer UDT-InstanzBeispiel
Teil 1: Die ActiveX-DLL -
Wie ich bereits erwähnt, Sie brauchen, um Ihre UDT öffentlich-zugänglich sind, um aufzuzählen mit Hilfe der TypeLib-Informationen-Komponente. Der einzige Weg dies zu tun ist, um Ihre UDT in einer public-Klasse in eine ActiveX-DLL oder ActiveX-EXE-Projekt. Andere Projekte, die in Ihrer Anwendung zugreifen zu können, müssen Sie den UDT ' s werden dann auf diese neue Komponente.
Folgen diesem Beispiel, erstellen Sie ein neues ActiveX-DLL-Projekt und nennen Sie es
UDTLibrary
.Anschließend benennen Sie die
Class1
Klasse-Modul (dieses wird standardmäßig Hinzugefügt, die von der IDE) zuUserTypes
und fügen Sie zwei benutzerdefinierte Typen der KlassePerson
undAnimal
:Listing 1:
UserTypes.cls
fungiert als container für unsere UDTNächsten, ändern die Instancing Eigenschaft für die
UserTypes
Klasse "2-PublicNotCreatable". Es gibt keinen Grund für jedermann zu instanziieren, dieUserTypes
Klasse direkt, weil es einfach als eine öffentliche container für unsere UDT.Schließlich, stellen Sie sicher, dass die
Project Startup Object
(unter Projekt->Eigenschaften) eingestellt ist auf "(None)" und das Projekt kompilieren. Sie sollten nun eine neue Datei namensUDTLibrary.dll
.Teil 2: Auflisten der UDT-Typ-Informationen
Jetzt ist es Zeit zu zeigen, wie wir Sie nutzen können TypeLib Objekt-Bibliothek zu implementieren, die eine
PrintUDT
Methode.Zunächst erstellen Sie ein neues Standard EXE-Projekt, und nennen Sie es wie immer Sie wollen. Fügen Sie einen Verweis auf die Datei
UDTLibrary.dll
das war in Teil 1 erstellt haben. Da will ich nur zeigen, wie dies funktioniert, werden wir im Direktfenster verwenden, um den code zu testen, schreiben wir.Erstellen Sie ein neues Modul, nennen Sie es
UDTUtils
und fügen Sie den folgenden code hinzu:Listing 2: Beispiel
PrintUDT
Methode und eine einfache test-MethodeTeil 3: so dass es Objekt-Orientiert
Die oben genannten Beispiele bieten eine "quick-and-dirty" - demonstration, wie Sie die TypeLib-Informationen Objekt-Bibliothek zum auflisten der Felder eines UDT. In einem real-world-Szenario, würde ich wahrscheinlich zu erstellen a
UDTMemberIterator
Klasse, würde Ihnen erlauben, mehr leicht iterieren über die Felder von UDT, zusammen mit einem Dienstprogramm-Funktion in ein Modul erstellt eineUDTMemberIterator
für einen bestimmten UDT-Instanz. Dies würde es Ihnen ermöglichen, etwas zu tun, wie die folgenden in Ihrem code, die viel näher an den pseudo-code, den Sie geschrieben in deiner Frage:Es ist eigentlich nicht allzu schwer zu tun, und wir können re-verwenden Sie den code aus dem
PrintUDT
routine erstellt in Teil 2.Zuerst, erstellen Sie ein neues ActiveX-Projekt und nennen Sie es
UDTTypeInformation
oder etwas ähnliches.Nächste, stellen Sie sicher, dass das Start-Objekt für das neue Projekt auf "(None)".
Das erste, was zu tun ist, erstellen Sie eine einfache wrapper-Klasse, die verstecken die details der
TLI.MemberInfo
Klasse aus dem Aufruf-code und machen es leicht, eine UDT-Feld mit Namen und Wert. Ich nannte diese KlasseUDTMember
. Die Instancing Eigenschaft für diese Klasse sollte PublicNotCreatable.Listing 3: Die
UDTMember
wrapper-KlasseNun müssen wir erstellen einen iterator-Klasse
UDTMemberIterator
, dass es uns erlauben wird, zu verwenden, VB -For Each...In
syntax zum Durchlaufen der Felder eines UDT-Instanz. DieInstancing
Eigenschaft für diese Klasse festgelegt werden solltePublicNotCreatable
(wir definieren eine utility-Methode später, erstellen von Instanzen im Namen der aufrufende code).EDIT: (2/15/09) ich gereinigt habe den code oben ein bisschen mehr.
Listing 4: Die
UDTMemberIterator
Klasse.Beachten Sie, dass, um diese Klasse iterierbar, so dass
For Each
verwendet werden können, müssen Sie bestimmte Verfahren Attribute für dasItem
und_NewEnum
Methoden (wie bereits in den Kommentaren im code). Sie können ändern Sie die Prozedur Attribute aus dem Menü Extras (Tools->Procedure Attribute).Endlich, wir brauchen eine utility-Funktion (
UDTMemberIteratorFor
im ersten code-Beispiel in diesem Abschnitt) zu schaffen, der eineUDTMemberIterator
für eine UDT-Instanz, welche dann iterativ mitFor Each
. Erstellen Sie ein neues Modul namensUtils
und fügen Sie den folgenden code:Listing 5: Die
UDTMemberIteratorFor
utility-Funktion.Schließlich, kompilieren Sie das Projekt und erstellen Sie ein neues Projekt zu testen.
In deinem test-Projekt, fügen Sie einen Verweis auf die neu erstellte
UDTTypeInformation.dll
und dieUDTLibrary.dll
in Teil 1 erstellt haben, und versuchen Sie den folgenden code in ein neues Modul:Listing 6: Test der
UDTMemberIterator
Klasse.Muss der code etwas Aufräumen, wie gut. GetWrappedmembersForUDT besonders rau.
+1 Ausgezeichnete Antwort, würde ich +2, wenn ich könnte.
Können Sie das konkretisieren? Ich Stimme zu, es ist nicht super elegant, aber wenn Sie irgendwelche spezifischen clean-up-Vorschläge/Ideen, um es schöner Aussehen, ich wäre daran interessiert zu hören.
Boah. Habe ganz vergessen zu Antworten, die den Wechsel automatisch zu wiki-Modus nach einer bestimmten Anzahl von Revisionen...
InformationsquelleAutor
@Dan,
Sieht es aus wie deine, versucht die RTTI eines UDT. Ich glaube nicht, dass Sie wirklich bekommen kann, die Informationen ohne wissen über die UDT-vor-Lauf-Zeit.
Um Ihnen den Einstieg versuchen:
Verständnis UDTs
Weil der nicht mit dieser Reflexion Fähigkeit. Ich würde meine eigene RTTI meine UDTs.
Geben Sie einen Basisplan. Versuchen Sie dies:
Schreiben Sie ein Programm, das öffnen jeder Quellcode-Datei und fügen Sie Die RTTI mit der name und der Typ der UDT. Wäre wohl besser, alle UDTs werden in einer gemeinsamen Datei.
Den RTTI wäre so etwas wie dieses:
"String:Lange:Lange:Lange:Integer"
Mit der Erinnerung an die UDT können Sie extrahieren Sie die Werte.
InformationsquelleAutor Gutzofter
Wenn Sie ändern Sie alle Ihre Arten zu den Klassen. Sie haben Optionen. Die große Gefahr der Veränderung von einer Art zu einer Klasse ist, müssen Sie verwenden die neue keyworld. Jedes mal, wenn es eine Deklaration einer variable vom Typ add new.
Dann können Sie die Variante verwenden, Stichwort oder CallByName. VB6 nicht anytype der Reflexion, aber Sie können Listen der Felder und testen, um zu sehen, wenn Sie vorhanden sind, zum Beispiel
Die Klasse Test hat die folgenden
Können Sie dann Folgendes tun
Wenn Sie versuchen, ein Feld, das nicht existiert, dann Fehler 438 angehoben werden. CallByName-ermöglicht die Verwendung von Zeichenfolgen zum aufrufen der Feld-und Methoden einer Klasse.
Was VB6 tut, wenn Sie deklarieren Dim as New ist sehr interessant und wird stark minimieren Fehler in dieser Konvertierung. Sehen Sie diese
nicht genauso behandelt, wie
Beispielsweise dies funktioniert
So wird ein Fehler
Der Grund dafür ist, dass im ersten Beispiel VB6 Flaggen T, so dass jederzeit ein Mitglied ist aufgerufen es zu überprüfen, ob die T ist auch nichts. Wenn es ist, es wird automatisch erstellen Sie eine neue Instanz der Testklasse und weisen Sie dann die variable.
Im zweiten Beispiel VB nicht dieses Verhalten.
In den meisten Projekt, die wir gründlich sicherzustellen, dass wir gehen Dim T as Test, T = New Test. Aber in Ihrem Fall, da Sie konvertieren möchten Typen in Klassen mit der geringsten Anzahl von Nebenwirkungen mit Dim T as New Test ist der Weg zu gehen. Dies ist, weil die Dim als Neue Ursache die variable imitieren die Art Typen, die Werke genauer an.
...Aber, ich bin einverstanden mit deinem Punkt hier. Für einen Typ hat, wurde in eine Klasse, es werden keine bestehenden Prüfungen für Nichts gegen Variablen von diesem Typ, so ist es nur ein Problem, wenn eine solche Prüfung ist später Hinzugefügt.
Ich der festen Mitarbeiter, die nicht formatiert als code sollte es klarer sein
Wow ... das ist wie ein Buch.
InformationsquelleAutor RS Conley