Hallo Profis,
Ich habe ein Problem mit Reflection in VB.net. Und zwar möchte ich
innerhalb eines TreeView´s ein paar DLLs (Bibliotheken) anzeigen lassen,
die dann nachher instanziiert werden können. Diese DLL´s enthalten
bedingt durch das .net-Framework noch weitere (Standard-)Klassen, die
ich bei der Auflistung in dem TreeView nicht so gerne dabei haben
möchte.
Der Code läuft in etwa so durch:
1
For Each AssemblyType As Type In Assembly.GetTypes
2
...GetProperties()
3
...GetMethods()
4
...GetEvents()
5
...GetConstructors()
6
...GetIrgendwieDieEnums()
7
Next
In der Application sollten aber die gelb hinterlegten und rot
eingerahmten Klassen nicht mit drinnen stehen! Ich finde jedoch keine
Möglichkeit, eine "eigene" Klasse, wie z.B. die "HelloWorldClass" zu
erkennen. Gibt es da irgendwo eine Property, um das auszulesen oder zu
separieren?
Edit: ich habe bereits sämtliche Verweise in der zu ladenden DLL
herausgenommen.
Des weiteren suche ich eine Möglichkeit, um an die Enumeration-Types
innerhalb einer Klasse zu kommen, und diese auszulesen.
Ich habe im Internet leider noch nichts passendes dazu gefunden.
Eventuell kann mir jemand von euch Weiterhelfen!?
Gruß, TS
Du kannst die eigenen Klassen mit einem Attribut markieren. Bei uns
machen wir das so für Erweiterungsschnittstellen (es wird eine DLL in
einer Config-Datei angegeben, in welcher sich dann eine oder mehrere mit
einem Attribut markierte Klasse befinden müssen, welche dann
instanziiert und als Erweiterung verwendet werden).
Eine weitere Möglichkeit wäre die Verwendung eines festen Name Patterns
bei den Klassennamen (My...) oder die Verwendung eines festen Namespace
(LibTsDLL.My). Das ist aber irgendwie gehacke...
Der eleganteste Weg ist die Markierung der relevanten Elemente (Klassen,
Structs, Enums, ...) mit einem Attribut, wie Sebastian bereits
geschrieben hat.
Markus
Danke für die Antworten. Die klassen über den Namespace zu "Markieren"
hatte ich mir zuerst auch überlegt! Ich dachte aber, dass es auch
irgendwie eleganter geht, und das das .net-Framework so eine
"Separierung" bereits enthält. Bzw. das die Internen Klassen solch eine
"Markierung" besitzen. Hmm, Also sollte ich am besten ein Attribut in
die "eigenen" Klassen setzten.
Meintest du das etwa so?
UserClassInterface.vb:
1
Public Interface UserClassInterface
2
ReadOnly Property IsUserClass As Boolean
3
ReadOnly Property IsInstanceable As Boolean
4
End Interface
-----
HelloWorldClass.vb:
1
Public Class HelloWorldClass
2
Implements UserClassInterface
3
4
Public ReadOnly Property IsInstanceable As Boolean Implements UserClassInterface.IsInstanceable
5
Get
6
Return True
7
End Get
8
End Property
9
10
Public ReadOnly Property IsUserClass As Boolean Implements UserClassInterface.IsUserClass
11
Get
12
Return True
13
End Get
14
End Property
15
16
DoSomething()
17
End Class
[edit]Ich werde es mal ausprobieren.[/edit]
Timmey S. schrieb:> Des weiteren suche ich eine Möglichkeit, um an die Enumeration-Types> innerhalb einer Klasse zu kommen, und diese auszulesen.
Ich kann nur dessen "Members" lesen, wenn ich den Type beim Namen kenne,
was in meinem Fall aber nicht geht. Ich hoffe ihr wisst, was ich damit
meine. Ich finde keine Möglichkeit, an die Enum´s per Reflection zu
kommen.
Danke für eure Ratschläge!
Gruß, TS
Attribute sind keine Interfaces. Es handelt sich dabei um
Meta-Informationen die an Klassen, Methoden, Properties, Felder, ...
angehängt werden und die über Reflection zur Laufzeit abgerufen werden.
Attribute verändern die eigentliche Klasse nicht. Eines der bekannteren
Attribute ist das SerializableAttribute. Wenn eine Klasse damit markiert
wird, gibt es im .NET-Framework Code, der in der Lage ist, Objekte
dieser Klasse zu serialisieren und wieder aus den serialisierten Daten
zu erzeugen.
In VB sähe das dann etwa so aus (ich kann kein VB, nur C# ;-)):
1
<Serializable()>
2
PublicClassTestSimpleObject
3
4
Publicmember1AsInteger
5
Publicmember2AsString
6
7
...
8
9
EndClass
Das .NET-Framework bietet die Möglichkeit, eigene Attribute zu
definieren. Attribute sind Klassen, die von System.Attribute ableiten.
Das könnte bei Dir dann so aussehen:
Dein Klassen versiehst Du dann mit dem neuen Attribut:
1
<UserClass()>
2
PublicClassHelloWorldClass
3
...
4
EndClass
Dann kannst Du Deine Klassen finden. Wie das genau geht, findest Du in
einem Beispiel in der MSDN-Doku zur Attribute Klasse:
http://msdn.microsoft.com/de-de/library/vstudio/system.attribute.aspxTimmey S. schrieb:> Timmey S. schrieb:>> Des weiteren suche ich eine Möglichkeit, um an die Enumeration-Types>> innerhalb einer Klasse zu kommen, und diese auszulesen.>> Ich kann nur dessen "Members" lesen, wenn ich den Type beim Namen kenne,> was in meinem Fall aber nicht geht. Ich hoffe ihr wisst, was ich damit> meine. Ich finde keine Möglichkeit, an die Enum´s per Reflection zu> kommen.
Deine Enums findest Du über Reflection als eigene Typen mit
Assembly.GetTypes unter Namespace.EnumName bei Enums, die außerhalb
einer Klasse definiert sind bzw. Namespace.KlassenName+EnumName bei
Enums, die innerhalb einer Klasse definiert wurden.
Das ganze kannst Du Dir ja mal im Debugger anschauen.
Grüße
Markus
Markus Volz schrieb:> Attribute sind keine Interfaces. Es handelt sich dabei um> Meta-Informationen die an Klassen, Methoden, Properties, Felder, ...> angehängt werden und die über Reflection zur Laufzeit abgerufen werden.
Ah, okay, ich hatte Attributen irgendwie mit den Propertys verwechselt,
und hatte daher zwei Propertys in ein Interface gesetzt. Ich hatte
bisher noch keine eigenen Attributen geschrieben.
Markus Volz schrieb:> Das .NET-Framework bietet die Möglichkeit, eigene Attribute zu> definieren. Attribute sind Klassen, die von System.Attribute ableiten.> Das könnte bei Dir dann...
Das hast du wirklich sehr verständlich beschrieben und gut rüber
gebracht. Danke für diese Aufklährung!
Markus Volz schrieb:> Deine Enums findest Du über Reflection als eigene Typen mit> Assembly.GetTypes unter Namespace.EnumName bei Enums, die außerhalb> einer Klasse definiert sind bzw. Namespace.KlassenName+EnumName bei> Enums, die innerhalb einer Klasse definiert wurden.
Also sind die Enums in dem "Bereich", der im obigen Bild als "Overhead"
markiert ist. Habe verstanden! Dann werde ich diese mit dem .IsEnum()
Property finden können. Danke für diesen Hinweis.
Gruß, TS
Timmey S. schrieb:> Ah, okay, ich hatte Attributen irgendwie mit den Propertys verwechselt,> und hatte daher zwei Propertys in ein Interface gesetzt. Ich hatte> bisher noch keine eigenen Attributen geschrieben.
Ok. Jetz weiß ich, wie Du auf ein Interface gekommen bist. Du hast
natürlich recht, Properties werden im Deutschen als Attribute
bezeichnet. :-)
Prinzipiell wäre Dein Ansatz, die Klassen über ein Interface zu
markieren, auch machbar. Dies müsste man in einer Sprache, die kein
Reflection kennt, so machen. Allerdings hat diese Vorgehensweise den
gravierenden Nachteil, dass sie Deine Klassenstruktur mit etwas
verunreinigt, das mit der eigentlichen Funktionalität nichts zu tun hat.
Grüße
Markus
Markus Volz schrieb:> Ok. Jetz weiß ich, wie Du auf ein Interface gekommen bist.Markus Volz schrieb:> Allerdings hat diese Vorgehensweise den> gravierenden Nachteil, dass sie Deine Klassenstruktur mit etwas> verunreinigt, das mit der eigentlichen Funktionalität nichts zu tun hat.
Das mit den Propertys klappt ganz gut innerhalb eines Projektes bzw.
Assemblys. Nur wie mache ich das mit externen DLLs / Librarys?
Diese Property-Klasse muss doch im "Main-Assembly" und auch in der zu
ladenden DLL vorhanden sein, oder? Also ganz genau die gleiche Klasse
bzw. Referenz!? Müssen diese auch von einem Assembly stammen??
Nach einigem herumprobieren konnte ich das nur mit einer art "Linker"
bzw. Brücken-DLL lösen, die diese "gemeinsam genutzen Klassen", wie
Propertys oder Schnittstellen enthalten! In der Main-Application und in
der zu ladenden DLL (die als "Erweiterung" dienen soll) wird dann darauf
verwiesen, damit die "gleichen Klassen" (aus nur einem Assembly)
verwendet werden!
Ich hoffe ihr versteht was ich meine, und was ich vor habe.
[edit]Macht man das überhaupt so ??????[/edit]
Siehe Anhang!
Gruß, TS!