Frage: Attribute verwenden.

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Frage: Attribute verwenden.

    Hallo,

    ich bin neulich auf die Attribute in VB.NET gestossen, ich habe mir die Beschreibung auf MSDN durchgelesen, verstehe aber immer noch nicht wie man sie verwendet.

    Bin bisher soweit gekommen, dass ich eine Attributsklasse habe:
    (Habe das mehr oder weniger verstanden.)

    VB.NET-Quellcode

    1. <AttributeUsage(AttributeTargets.All, AllowMultiple := False, Inherited := True)> _
    2. Public Class MyAttribute
    3. Inherits Attribute
    4. Public Property Vorname() As String
    5. Get
    6. Return m_Vorname
    7. End Get
    8. Set
    9. m_Vorname = Value
    10. End Set
    11. End Property
    12. Private m_Vorname As String
    13. Public Property Nachname() As String
    14. Get
    15. Return m_Nachname
    16. End Get
    17. Set
    18. m_Nachname = Value
    19. End Set
    20. End Property
    21. Private m_Nachname As String
    22. End Class


    Und wie ich die Attribute dan festlege:
    (Ist recht simpel zu verstehen.)

    VB.NET-Quellcode

    1. <My(Vorname := "Viktor", Nachname := "M")> _
    2. Public Class Irgentwas
    3. End Class


    Was ich aber noch garnicht verstanden habe ist, wie ich auf diese festgelegten Attribute dann in der Irgentwas Klasse zugreifen kann.
    Kennt sich einer damit aus und weis mir zu helfen?
    Attribute arbeiten sind ziemlich weit hinter den Kulissen.
    Sie werden per Reflection ausgelesen und ausgewertet.
    Das nutzen üblicherweise verschiedenste Designer und Generatoren, oder auch das Verhalten bei Serialisierung kann damit gesteuert werden.

    Ein einfaches Beispiel:
    mach eine einfache Klasse

    VB.NET-Quellcode

    1. Public Class MyComponent1 : Inherits System.ComponentModel.Component
    2. End Class

    Im Projekt-Explorer wird die dir jetzt mit dem Component-Icon angezeigt, und bei Doppelklick öffnet sich der (in diesem Falle blöde) Component-Designer.

    Füge das DesignerCategory-Attribute hinzu:

    VB.NET-Quellcode

    1. <System.ComponentModel.DesignerCategory("code")> _
    2. Public Class MyComponent1 : Inherits System.ComponentModel.Component
    3. End Class

    Jetzt, im ProjectExplorer, bei Doppelklick drauf öffnet sich der Code-Editor.

    Selbst Attribute zu schreiben ist nur sinnvoll, wenn man sich auch mit Reflection rumärgern will ;)

    VB.NET-Quellcode

    1. Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    2. Dim cmp As New MyComponent1
    3. Dim tp = cmp.GetType
    4. For Each attr As Attribute In tp.GetCustomAttributes(True)
    5. MsgBox(attr.GetType.Name)
    6. Next
    7. End Sub


    Hingegen bereits vorhandene Attribute zu setzen, kann sehr nützlich sein, um wie gesagt, das Verhalten der IDE, Serialisierung uvm. zu beeinflussen.
    Was ich jetzt damit erreichen möchte ist:

    ich schreibe eine Bibliothek zur Steuerung einer anderen Bibliothek Engine und das Ziel ist es, dass der End Benutzer mit wenig Programmierkenntnissen sich selbst eine kleine KI schreiben kann. (Beispiel: AntMe)

    Und ich finde diese Art der Benutzung von Attributen ist eigentlich sehr simpel für jemanden der kaum Ahnung von Programmieren hat.

    Was ich jetzt noch nicht weis ist, wie kann ich dan in der z.B. Basis Klasse von Irgentwas oder direkt in dieser Klasse die vom Benutzer reingeschriebenen Einstellungen auswerten.

    Soviel wie ich auf deiner Erklerung zum Auslesen der Attribute verstanden habe ist, dass man sich z.B. eine eigene Methode schreiben muss um sie auszulesen.
    z.B. sowas:

    VB.NET-Quellcode

    1. //Pseudocode
    2. Public Function GetVorname() As String
    3. Dim attr As New MyAttribute()
    4. Dim typ = attr.GetType
    5. For Each attrb As Attribute In tp.GetCustomAttributes(True)
    6. IF attrb.GetType.Name = "Vorname" Then Return attrb.GetType.Value
    7. Next
    8. End Funktion


    Habe ich das soweit richtig verstanden?

    Info: Weitere Ideen, Anregungen ... sind NICHT fehl am Platz!!!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ViktorS“ ()

    Ja, in dem Fall ists evtl. sinnvoll, attribute zu proggen. Beim Unit-Testing wird glaub auch die Test-Engine durch eigens dafür designete Attribute gesteuert, das ist vmtl in etwa vergleichbar (ich glaube und vermute: weil von UnitTests habich kein schimmer ;) )

    Dein Code ist natürlich sehr pseudo, die Klasse Type (Rückgabewert von Gettype) stellt kein Value bereit.
    Wenn du ein passendes Attribut gefunden hast, mußt du es auf den korrekten Attribute-Typ casten, vorzugsweise mit DirectCast, dann hast du Zugriff auf dessen Properties.
    Vielmehr Anregungen weißichnich, du wirst dich da schon hineinwursteln.

    Insgesamt kann man Attribute verstehen, als eine Art erweiterte Property eines Typen, nicht des konkreten Objektes. Wenn man dann ein Objekt hat, kann man sich per Gettype den Typen holen, und davon die Attribute.

    Was ist AWE?
    Habs hingekriegt :)


    Lösung:

    VB.NET-Quellcode

    1. public class AnimalTypeAttribute : Inherits Attribute
    2. Public Property Pet() As String;
    3. end class
    4. <AnimalType(
    5. Pet = "Maja"
    6. )> _
    7. class AnimalTypeTestClass
    8. end class
    9. class DemoClass
    10. Public Shared Function GetDemo() As String
    11. Dim ret As String = ""; //Nur dazu da, um einen Rückgabewert dynamisch zu generieren. (Muss auch direkt inizialisiert werden!!!)
    12. Dim testClass As New AnimalTypeTestClass(); //Anlegen eines neuen Objekts.
    13. Dim mInfo As MemberInfo = testClass.GetType(); //Übergabe des Typs des Objekts.
    14. //Durchsuchen nach Atributen in diesem Objekt.
    15. For Each attr As Attribute In Attribute.GetCustomAttributes(mInfo)
    16. If attr.[GetType]() = GetType(AnimalTypeAttribute) Then
    17. ret += mInfo.Name + "->" & DirectCast(attr, AnimalTypeAttribute).Pet; //Ausgabe
    18. End If
    19. Next
    20. Return ret; //Rückgabe
    21. End Function
    22. End Class
    23. '->Console.WriteLine(GetDemo());
    24. 'Ausgabe: AnimalTypeTestClass->Maja


    ########################

    AWE steht für Anwendungsentwicklung. (Stichwort: Fachinformatiker für Anwendungsentwicklung)

    ViktorS schrieb:

    VB.NET-Quellcode

    1. If attr.GetType() = GetType(AnimalTypeAttribute) Then

    Hierzu habe ich 2 Senfe, zum dazugeben:
    1) war ich irritiert, dass man Typen per = vergleichen kann, aber tatsächlich: Der = - Operator ist für Type definiert. Ich verwende immer den Is-Operator, der ist glaub schneller.
    Am Is-Operator ist auch interessant, dass attr.GettType dieselbe Typ-Instanz liefert wie Gettype(AnimalTypeAttribute). Gewissermaßen sieht man daran auch, dasses sich bei Typen um nicht-instanzierbare MetaInformation handelt.
    2) zu überlegen wäre, ob man den ebenfalls sehr schnellen TypeOf Is - Operator verwendet

    VB.NET-Quellcode

    1. If TypeOf attr Is AnimalTypeAttribute Then
    der macht aber eine andere Aussage, nämlich, ob attr ein AnimalTypeAttribute ist, oder davon erbt.

    Beides im Grunde schnuppe, ist alles schnell (am langsamsten wird .GetAttributes() sein). Sicherlich macht auch der =- Operator intern einen Is - Vergleich und fertig.

    Sieht eiglich weniger schlimm aus, alsich erwartet. Unangenehmer wird Reflection, wenn man mit PropertyInfo = Type.GetProperty() und Value = PropertyInfo.GetValue() rumwurstelt. Das ist langsam und die Rückgabewerte haben so komische Typen, da ist man dann nurnoch am casten.

    Kleine Bitte noch: mach entweder c#- oder vb- Samples, nicht dieses kuriose Gemisch ;) Ich hab am liebsten abgeschlossene Einheiten , die ich in irgendeine IDE pasten kann, ohne gleich sonstwie dran rum bauen zu müssen, dass der Compiler zufrieden ist (hasteja eigentlich, nur dassich kein Compiler hab, der vb# kann;)).
    Ohne IDE kannich keine 2 Zeilen korrekten Code produzieren.
    Hey das ist DIE IDEEE, einfach einen VB# Compiler schreiben^^


    Getesteter C# Beispielsquellcode:
    Spoiler anzeigen

    Quellcode

    1. public class AnimalTypeAttribute : Attribute
    2. {
    3. public string Pet{ get; set; }
    4. }
    5. [AnimalType(
    6. Pet = "Maja"
    7. )]
    8. class AnimalTypeTestClass
    9. {
    10. }
    11. class DemoClass
    12. {
    13. public static string GetDemo()
    14. {
    15. string ret = "";
    16. AnimalTypeTestClass testClass = new AnimalTypeTestClass();
    17. MemberInfo mInfo = testClass.GetType();
    18. foreach (Attribute attr in Attribute.GetCustomAttributes(mInfo))
    19. {
    20. if (attr.GetType() == typeof(AnimalTypeAttribute))
    21. ret += mInfo.Name + "->" + ((AnimalTypeAttribute)attr).Pet;
    22. }
    23. return ret;
    24. }
    25. }
    26. //Console.WriteLine(DemoClass.GetDemo());
    27. //Ausgabe: 'AnimalTypeTestClass->Maja'



    Habe mir überlegt dazu eine Lib zu schreiben, weil es schon ziemlich umständlich ist eine ganze Methode zu schreiben nur um einen Wert auszulesen. Werde dabei die Geschwindigkeit optimieren. (Soweit meine Erfahrungen reichen.)

    Wen Bedarf da ist werde ich mir die Mühe machen das Ding in VB zu schreiben und unter Libraris veröffentlichen.
    Ist mein Post unsichtbar? Wie gesagt, du musst keine eigene Methode schreiben:

    VB.NET-Quellcode

    1. Public Shared Function GetDemo() As String
    2. Dim type As Type = GetType(AnimalTypeTestClass)
    3. Dim petAttributes() As AnimalTypeAttribute = DirectCast(type.GetCustomAttributes(GetType(AnimalTypeAttribute), True), AnimalTypeAttribute())
    4. If petAttributes.Length = 0 Then
    5. Throw New NullReferenceException()
    6. ElseIf petAttributes.Length = 1 Then
    7. Return String.Concat(type.Name, "->", petAttributes(0).PetName)
    8. Else
    9. Throw New AmbiguousMatchException("Multiple attributes defined. This should not happen since the AllowMultiple-Value of the AttributeUsage-Attribute is hopefully set to true =).") 'Heißt doch irgendwie so
    10. End If
    11. End Function


    Ich hoff mal, ich hab jetzt beim hier tippen nichts übersehen. Wenn du schon hier Fragen stellst, dann bitte in VB. Wir sind ein Vb-Forum und kein C#-Forum! Hier gibts einen C# to VB-Converter (und zurück) developerfusion.com/tools/convert/csharp-to-vb/

    Gruß
    ~blaze~