Benutzer mit den meisten Antworten
dynamische Klassen...

Frage
-
und noch 2 Sachen :
a) kann ich prüfen ob eine Klasse eine bestimmte Funktion oder Sub hat ? Irgendwie so mit HasFunction(oPersonal, "MenuRecordSave") ?
b) kann ich Klassen auch dynamisch erzeugen ? z.B.CLASS A
private Func XYZ()
return 0CLASS B
private Func XYZ()
return 0
CLASS C
private sub InitalleandereKlassen()
dim aKlassen as ARRAYaKlassen = {"CLASSA","CLASSB"}
end sub
nun möcht ich diese Klassen in dem Array einmal erzeugen und die Methode/Sub XYZ anspringen und dann wieder
schliessen...
Das Array wird später ca. 400 Objekte beinhalten also möcht ich mir das händische tippen erleichtern :)Mario
Antworten
-
Hallo Mario,
a) kann ich prüfen ob eine Klasse eine bestimmte Funktion oder Sub hat ? Irgendwie so mit HasFunction(oPersonal, "MenuRecordSave") ?
Ja, das geht mittels Reflection. Mal in einem einfachen Beispiel:
' Imports System.Reflection Public Function HasMethod(ByVal obj As Object, ByVal name As String) As Boolean Dim mi As MethodInfo = obj.GetType.GetMethod(name, BindingFlags.Instance Or _ BindingFlags.Public Or _ BindingFlags.NonPublic) Return mi IsNot Nothing End Function
b) kann ich Klassen auch dynamisch erzeugen ? z.B.
Wenn ich Dich hier richtig verstehe, möchtest Du die Klasse dynamisch auf Basis einer Zeichenfolge instantiieren, richtig?
Dim o As Object Dim t As System.Type t = Assembly.GetExecutingAssembly().GetType("WindowsApplication1.Class1") o = Activator.CreateInstance(t) If o IsNot Nothing Then Dim mi As MethodInfo = t.GetMethod("Foo", BindingFlags.Instance Or _ BindingFlags.Public) If mi IsNot Nothing Then mi.Invoke(o, Nothing) End If End If
Kurz erklärt: Aus dem aktuell ausführendem Assembly wird der Typ auf Basis des vollständigen Klassennamens ermittelt. Beachte hier, dass der angegebene Namespace ggf. anzupassen ist, je nachdem welchen Stammnamespace Du in den Projekt Eigenschaften bzw. die Namespace Anweisung festgelegt hast. Activator.CreateInstance erstellt eine Instanz aus diesem Typ. Danach erfolgt die bereits im ersten Beispiel gezeigte Ermittlung der Methode und der Aufruf selbiger.
Du solltest aber beachten, dass Reflection auf Seiten der Runtime eine eher aufwändige Angelegenheit ist und sich negativ auf die Performance auswirken kann. Gerade wenn Du hier später 400 Objekte ins Spiel bringen möchtest. Vielleicht magst Du ja den Hintergrund Deines Vorgehens erklären. So kann man sehen, ob es bessere Herangehensweisen gibt.
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de- Als Antwort markiert Robert Breitenhofer Donnerstag, 8. Juli 2010 15:30
-
Hallo Mario,
Das dynamische Erzeugen der Klassen sind nacher Klassen für jede Tabelle im SQL/Access Datenbank. Diese Klassen behinhalten die aktuelle Strutkur, Indexe, genauere Feldbeschreibungen, Eingabemaskenformate für Textboxen, Delete Methoden um abhängige Tabelleneinträge unter Umständen ebenfalls mit zu löschen ) und viele weitere Informationen.
Klingt fast so, als wolltest Du einen O/R Mapper, wie das Entity Framework noch einmal neu erfinden.
JEde Klasse verfügt über ein und die selbe Function nur zur Sicherheit deshalb die Abfrage mit "Hasfunktion" falls jemand anderes mal diese Funkttion später vergisst an der Klasse das zu definieren...
Dass Klassen über bestimmte Eigenschaften und Methoden verfügen, legt man in der OOP meist über Interfaces fest. Damit kannst Du eine Klasse erzeugen und prüfst, ob die Klasse dieses Interface implementiert. Wenn sie das macht, kannst Du über dieses Interface typsicher auf die Methode zugreifen und kannst sicher sein, dass sie implementiert vorhanden ist. Am Beispiel von gestern:
Public Interface IFoo Sub Foo() End Interface Public Class Class1 Implements IFoo Public Sub Foo() Implements IFoo.Foo MsgBox("Foo") End Sub End Class ' Anwendung: Dim o As Object Dim t As System.Type Dim lClass As String = "CreateInstanceAndMethodInfo.Class1" t = Assembly.GetExecutingAssembly().GetType(lClass) If t IsNot Nothing Then o = Activator.CreateInstance(t) If TypeOf o Is IFoo Then DirectCast(o, IFoo).Foo() End If End If
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de- Bearbeitet Thorsten Dörfler Donnerstag, 1. Juli 2010 10:17 Formulierungsdetail
- Als Antwort markiert Robert Breitenhofer Donnerstag, 8. Juli 2010 15:30
Alle Antworten
-
Hallo Mario,
a) kann ich prüfen ob eine Klasse eine bestimmte Funktion oder Sub hat ? Irgendwie so mit HasFunction(oPersonal, "MenuRecordSave") ?
Ja, das geht mittels Reflection. Mal in einem einfachen Beispiel:
' Imports System.Reflection Public Function HasMethod(ByVal obj As Object, ByVal name As String) As Boolean Dim mi As MethodInfo = obj.GetType.GetMethod(name, BindingFlags.Instance Or _ BindingFlags.Public Or _ BindingFlags.NonPublic) Return mi IsNot Nothing End Function
b) kann ich Klassen auch dynamisch erzeugen ? z.B.
Wenn ich Dich hier richtig verstehe, möchtest Du die Klasse dynamisch auf Basis einer Zeichenfolge instantiieren, richtig?
Dim o As Object Dim t As System.Type t = Assembly.GetExecutingAssembly().GetType("WindowsApplication1.Class1") o = Activator.CreateInstance(t) If o IsNot Nothing Then Dim mi As MethodInfo = t.GetMethod("Foo", BindingFlags.Instance Or _ BindingFlags.Public) If mi IsNot Nothing Then mi.Invoke(o, Nothing) End If End If
Kurz erklärt: Aus dem aktuell ausführendem Assembly wird der Typ auf Basis des vollständigen Klassennamens ermittelt. Beachte hier, dass der angegebene Namespace ggf. anzupassen ist, je nachdem welchen Stammnamespace Du in den Projekt Eigenschaften bzw. die Namespace Anweisung festgelegt hast. Activator.CreateInstance erstellt eine Instanz aus diesem Typ. Danach erfolgt die bereits im ersten Beispiel gezeigte Ermittlung der Methode und der Aufruf selbiger.
Du solltest aber beachten, dass Reflection auf Seiten der Runtime eine eher aufwändige Angelegenheit ist und sich negativ auf die Performance auswirken kann. Gerade wenn Du hier später 400 Objekte ins Spiel bringen möchtest. Vielleicht magst Du ja den Hintergrund Deines Vorgehens erklären. So kann man sehen, ob es bessere Herangehensweisen gibt.
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de- Als Antwort markiert Robert Breitenhofer Donnerstag, 8. Juli 2010 15:30
-
Hallo Thorsten,
super vielen Dank! Werde es gleich heute Nachmittag ausprobieren.
Das dynamische Erzeugen der Klassen sind nacher Klassen für jede Tabelle im SQL/Access Datenbank. Diese Klassen behinhalten die aktuelle Strutkur, Indexe, genauere Feldbeschreibungen, Eingabemaskenformate für Textboxen, Delete Methoden um abhängige Tabelleneinträge unter Umständen ebenfalls mit zu löschen ) und viele weitere Informationen.
Schätzungsweise werden es ca. 400 Tabellen später werden. Und somit will ich jede Klasse bei Programmstart einmal erzeugen, die Klasse sich selbst auf Struktur ( mit ggfs. Update ) und Vorhandensein prüfen lassen. Das funtkioniert schon alles. Nur muss ich das Objekt zur Zeit noch "händisch eintippen".. JEde Klasse verfügt über ein und die selbe Function nur zur Sicherheit deshalb die Abfrage mit "Hasfunktion" falls jemand anderes mal diese Funkttion später vergisst an der Klasse das zu definieren...
bye,
Mario
-
Hallo Mario,
Das dynamische Erzeugen der Klassen sind nacher Klassen für jede Tabelle im SQL/Access Datenbank. Diese Klassen behinhalten die aktuelle Strutkur, Indexe, genauere Feldbeschreibungen, Eingabemaskenformate für Textboxen, Delete Methoden um abhängige Tabelleneinträge unter Umständen ebenfalls mit zu löschen ) und viele weitere Informationen.
Klingt fast so, als wolltest Du einen O/R Mapper, wie das Entity Framework noch einmal neu erfinden.
JEde Klasse verfügt über ein und die selbe Function nur zur Sicherheit deshalb die Abfrage mit "Hasfunktion" falls jemand anderes mal diese Funkttion später vergisst an der Klasse das zu definieren...
Dass Klassen über bestimmte Eigenschaften und Methoden verfügen, legt man in der OOP meist über Interfaces fest. Damit kannst Du eine Klasse erzeugen und prüfst, ob die Klasse dieses Interface implementiert. Wenn sie das macht, kannst Du über dieses Interface typsicher auf die Methode zugreifen und kannst sicher sein, dass sie implementiert vorhanden ist. Am Beispiel von gestern:
Public Interface IFoo Sub Foo() End Interface Public Class Class1 Implements IFoo Public Sub Foo() Implements IFoo.Foo MsgBox("Foo") End Sub End Class ' Anwendung: Dim o As Object Dim t As System.Type Dim lClass As String = "CreateInstanceAndMethodInfo.Class1" t = Assembly.GetExecutingAssembly().GetType(lClass) If t IsNot Nothing Then o = Activator.CreateInstance(t) If TypeOf o Is IFoo Then DirectCast(o, IFoo).Foo() End If End If
Thorsten Dörfler
Microsoft MVP Visual Basic
vb-faq.de- Bearbeitet Thorsten Dörfler Donnerstag, 1. Juli 2010 10:17 Formulierungsdetail
- Als Antwort markiert Robert Breitenhofer Donnerstag, 8. Juli 2010 15:30
-
Hallo Mario,
da sich solche Informationen nicht sekündlich ändern,
sollte man dies bereits vorher erstellen.So bieten sich zum Beispiel Generatoren an wie TT4 Templates,
die die Klassen (vergleichbar mit typisierten DataSets) vorher erzeugen.Wobei ich Dir empfehlen würde, Dich mit gängigen ORMs wie
Entity Framework, NHibernate zu beschäftigen.
Oder wenn Du meinst, es dynamisch haben zu müssen, siehe z. B. Subsonic
Ein Selbstbau an der Stelle ist mit einigen Risiken und nicht zu
unterschätzenden Aufwand verbunden, denn die Tücke liegt
dort im Detail.Gruß Elmar