Forum: PC-Programmierung Vb.Net Reflection - Assembly auslesen


von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

: Bearbeitet durch User
von Sebastian L. (der_mechatroniker)


Lesenswert?

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).

von Markus V. (valvestino)


Lesenswert?

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

von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Lesenswert?

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

: Bearbeitet durch User
von Markus V. (valvestino)


Lesenswert?

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
  Public Class TestSimpleObject
3
  
4
     Public member1 As Integer
5
     Public member2 As String
6
7
     ...
8
  
9
  End Class

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:
1
  Public Class UserClassAttribute Extends System.Attribute
2
  End Class

Dein Klassen versiehst Du dann mit dem neuen Attribut:
1
  <UserClass()>
2
  Public Class HelloWorldClass
3
     ...
4
  End Class

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.aspx

Timmey 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

von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Lesenswert?

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

von Markus V. (valvestino)


Lesenswert?

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

von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Angehängte Dateien:

Lesenswert?

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!

: Bearbeitet durch User
von Tim S. (Firma: tsx89) (freak_ts) Benutzerseite


Lesenswert?

Timmey S. schrieb:
> 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

Kennt jemand eine Möglichkeit, ein Assembly mit den Klassen darin 
Rekursiv zu durchlaufen??

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.