| 

.NET C# Java Javascript Exception

3
Seit .NET 4.5 lassen sich beliebige Metadaten als Namen-Wert-Paare in Assemblies ablegen, in der Regel über die Datei AssemblyInfo.cs in C# und die Datei AssemblyInfo.vb in VB.NET. In C# sieht das so aus:

[assembly: System.Reflection.AssemblyMetadata("Funktion", 
"Anzeige von Geschäftsgrafiken")]


In VB.NET so:

<Assembly: AssemblyMetadata("Funktion", "Anzeige von Geschäftsgrafiken")]


Die Werteabfrage ist nicht über den Windows Explorers, sondern ausschließlich per Reflection möglich. Ferner sind nur statische Werte zulässig. Eine Lösung zur Abfrage aller Schlüssel-Werte-Paare aus einem ausgeführten Assembly heraus erfolgt - hier in VB.NET - so:

Imports System.Reflection
...
Dim MyAssembly As Assembly =
Assembly.GetExecutingAssembly()
With MyAssembly
Dim AttributListe As AssemblyMetadataAttribute() =
.GetCustomAttributes(GetType(AssemblyMetadataAttribute), False)
If AttributListe.Length > 0 Then
For Each Element As AssemblyMetadataAttribute In AttributListe
MsgBox("Key: " & Element.Key & " | Wert: " & Element.Value)
Next
End If
End With


Gibt es auch eine Methode, um den Wert eines bestimmten Schlüssels direkt abzufragen? Ich habe nichts entsprechendes gefunden. Oder muss ich immer alle Schlüssel/Werte durchlaufen oder mir eine entsprechende Methode selbst basteln?
01.08.2013
David G. 191 1 6
2 Antworten
2
Eine Methode, um den Wert eines bestimmten Schlüssels direkt abzufragen, wirst Du Dir selber basteln müssen. Wenn Du Deine mittels Reflection gefundenen Ergebnisse in einem geeigneten Cache ablegst, erreichst Du nach dem einmaligen Laden (Reflection) nahezu einen O(1) Zugriff. Das funktioniert aber nur, wenn die Keys aller Attribute eindeutig sind. Ansonsten kannst Du einen Lookup verwenden.

Hier ein Beispiel in C# (VB.NET ist nicht meine Muttersprache) mit der Annahme eindeutiger Schlüssel:
var cache =
Assembly
.GetExecutingAssembly()
.GetCustomAttributes<AssemblyMetadataAttribute>()
.ToDictionary(a => a.Key, a => a.Value);

string function = cache["Funktion"];

Und hier als Lookup bei nicht eindeutigen Schlüsseln (der Unterschied ist, dass Du bei einem Dictionary pro Schlüssel nur einen Wert hast, bei einem Lookup steckt hinter einem Key ein IEnumerable<Value>).
var lookup =
Assembly
.GetExecutingAssembly()
.GetCustomAttributes<AssemblyMetadataAttribute>()
.ToLookup(a => a.Key, a => a.Value);

IEnumerable<string> allFunctions = lookup["Funktion"];

Das könntest Du dann noch in eine eigene Klasse verpacken...
01.08.2013
ffordermaier 8,4k 3 9
Das ist wirklich eine sehr interessante Lösung, danke... habe das mal in die Syntax von VB.NET konvertiert und alternativ eine Funktion definiert, die die Info über eine benutzerdefinierte Funktion zu einem beliebigen Assembly zurückliefert. Auf die dauerhafte Speicherung der Werte in einem Cache wird dabei allerdings verzichtet.
David G. 02.08.2013
1
In VB.NET sieht die Lösung von @fforderrmaier ein wenig anders aus. Hier die Anlage des Dictionaries:

Dim cache As Dictionary(Of String, String) =
Assembly.GetExecutingAssembly().GetCustomAttributes(Of
AssemblyMetadataAttribute).ToDictionary(Function(a) a.Key,
Function(a) a.Value)
Dim [function] As String = cache("Funktion")


Und hier das zugehörige Lookup:

Dim lookup = Assembly.GetExecutingAssembly().GetCustomAttributes(Of 
AssemblyMetadataAttribute)().ToLookup(Function(a) a.Key,
Function(a) a.Value)
Dim allFunctions As IEnumerable(Of String) = lookup("Funktion")


Und wer die Rückgabe über eine Funktion bevorzugt, kann die benutzerdefinierte Funktion GetValue nutzen. Wichtig ist, das der Reflection-Namespace via Imports System.Reflection einzubinden ist:

Function GetValue(ByVal Assembly As Assembly, ByVal Keyname As String) As String
Dim kValue As String = ""
With Assembly
Dim AttributListe As AssemblyMetadataAttribute() =
.GetCustomAttributes(GetType(AssemblyMetadataAttribute), False)
If AttributListe.Length > 0 Then
For Each Element As AssemblyMetadataAttribute In AttributListe
If Keyname = Element.Key Then
kValue = Element.Value
Exit For
End If
Next
End If
End With
Return kValue
End Function


Und zur Ergänzung, das aufrufende Assembly, das man an die Funktion Getvalue übergibt, kann mit

Dim MyAssembly As Assembly = Assembly.GetCallingAssembly()


bestimmt werden. Das Assembly zu einem ausgeführten Programm erhält man damit:

Dim MyAssembly As Assembly = Assembly.GetExecutingAssembly()
02.08.2013
David G. 191 1 6

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH