none
Custom Attribut aus Extension Methode lesen RRS feed

  • Frage

  • Hallo Forum,

    ich habe eine Extension Class mit statischen Methoden für die ich Custom Attribute definiert haben.
    Ausser den statischen Methoden in der Extension Class kann ich alle Member lesen.
    Wie bekomme ich es nun hin per Reflection auch die Custom Attribute der statischen Klasse zu lesen.

    Danke und Gruß
    Gerhard Ahrens

    Donnerstag, 27. Juli 2017 06:07

Antworten

  • Hallo Gerhard,

    bei deinem Code steigt der bereits weit vor der Ermittlung der Methoden aus (und dabei ist es egal, ob ich das Attribut auf einer Instanz- oder einer statischen Methode anwende). Daher denke ich mal, dass das Problem mit deinem Code nichts mit statisch oder nicht statisch zu tun hat.

    if( type.IsPublic == true && type.GetCustomAttributes( typeof( TValue ), true ).Length > 0 )

    sorgt (zumindest in meiner Testanwendung) dafür, dass die Schleife aussteigt, da es keine Klasse gibt, die das LibraryDoc Attribut verwendet. In deinem Fall ist das wohl genauso.

    Zudem rufst Du die identische Methode zweimal auf, was letztendlich eine schlechtere Performance zur Folge hat.

    Einmal eben:

    if( type.IsPublic == true && type.GetCustomAttributes( typeof( TValue ), true ).Length > 0 )

    und direkt dahinter nochmal:

    dynamic attr = type.GetCustomAttributes( typeof( TValue ), true )

    Macht natürlich wenig Sinn.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 27. Juli 2017 08:41
    Moderator

Alle Antworten

  • Hallo Gerhard,

    poste bitte den Code, mit dem Du die Attribute für die normalen Methoden ausliest.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 27. Juli 2017 06:22
    Moderator
  • Hallo Stefan,

    das ist, denke ich der relevante Teil. Ich will alle Attribute vom Typ "LibraryDocAttribute" in eine Liste packen. Wie geschrieben, klappt das bei allen Member, nur bei den aus einer Extension Klasse nicht. Mit den BindungsFlags habe ich auch verschiedene Varianten probiert.

    private List<TValue> GetClassAttribute<TValue>(Assembly assembly) where TValue : Attribute
    {
       List<TValue> attrList = new List<TValue>();
       BindingFlags bindingFlags = BindingFlags.Static 
    | BindingFlags.Public
    | BindingFlags.Instance
    | BindingFlags.NonPublic
    | BindingFlags.FlattenHierarchy; foreach (Type type in assembly.GetTypes().AsParallel()) { if (type.IsPublic == true &&
    type.GetCustomAttributes(typeof(TValue), true).Length > 0) { dynamic attr = type.GetCustomAttributes(typeof(TValue), true)
    .Cast<TValue>()
    .FirstOrDefault<TValue>(); if (attr == null) { continue; } attr.Namespace = type.Namespace; attr.MemberName = type.Name; attrList.Add(attr as TValue); PropertyInfo[] properties = type.GetProperties(bindingFlags); foreach (var property in properties.AsParallel()) { object[] attributes = property.GetCustomAttributes(typeof(TValue), true); foreach (var attribute in attributes.AsParallel()) { if (attribute.GetType() == typeof(TValue)) { dynamic attrMember = attribute; attrMember.Namespace = type.Namespace; attrMember.ClassName = type.Name; attrMember.MemberName = property.Name; attrMember.MemberTyp = property.MemberType.ToString(); attrMember.ReturnTyp = property.PropertyType.Name; attrList.Add(attrMember as TValue); } } } MethodInfo[] methodes = type.GetMethods(bindingFlags); foreach (var methode in methodes.AsParallel()) { object[] attributes = methode.GetCustomAttributes(typeof(TValue), true); foreach (var attribute in attributes.AsParallel()) { if (attribute.GetType() == typeof(TValue)) { dynamic attrMember = attribute; attrMember.Namespace = type.Namespace; attrMember.ClassName = type.Name; attrMember.MemberName = methode.Name; attrMember.MemberTyp = methode.MemberType.ToString(); attrMember.ReturnTyp = methode.ReturnParameter.ToString(); attrMember.IsStatic = methode.IsStatic; attrMember.Parameters = this.ParameterToString(methode.GetParameters()); attrList.Add(attrMember as TValue); } } } } } return attrList; }


    Donnerstag, 27. Juli 2017 06:40
  • Hi Gerhard,
    hast Du auch BindingsFlags.Static gesetzt?

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 27. Juli 2017 06:49
  • Hallo Peter,

    ja, das kannst Du im Source sehen.

    BindingFlags bindingFlags = BindingFlags.Static 
    | BindingFlags.Public
    | BindingFlags.Instance
    | BindingFlags.NonPublic
    | BindingFlags.FlattenHierarchy;

    Gruß
    Gerhard

    Donnerstag, 27. Juli 2017 07:14
  • Hi Gerhard,
    Static ist aber keine Instance.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Donnerstag, 27. Juli 2017 07:28
  • Hallo Peter,

    die BindingsFlags ändern nichts am Ergebnis. Die Attribute aus der statischen Klasse bekomme ich nicht zu sehen.
    Eventuell macht die Kombination "public static class" und "public static Methode" in Reflection ein Problem. Ich könne mir auch auch nicht erklären warum.

    Gruß
    Gerhard

    Donnerstag, 27. Juli 2017 07:49
  • Hallo Gerhard,

    ich verstehe den Sinn eines Teils deines Codes nicht, daher habe ich mal eine rudimentäre Methode erstellt, um die CustomAttributes der Methoden (auch statischer Methoden) auszulesen.

    private List<TValue> GetCustomAttributes<TValue>( Assembly assembly ) where TValue : Attribute
    {
        List<TValue> attrList = new List<TValue>();
        BindingFlags bindingFlags =   BindingFlags.Static 
                                    | BindingFlags.Public 
                                    | BindingFlags.Instance 
                                    | BindingFlags.NonPublic 
                                    | BindingFlags.FlattenHierarchy;
    
        foreach( Type type in assembly.GetTypes().AsParallel() )
        {
            MethodInfo[] methods = type.GetMethods( bindingFlags );
            foreach ( var method in methods.AsParallel() )
            {
                object[] attributes = method.GetCustomAttributes( typeof( TValue ), true );
    
                foreach (var attribute in attributes.AsParallel() )
                {
                    if( attribute.GetType() == typeof( TValue ) )
                    {
                        attrList.Add( attribute as TValue );
                    }
                }
            }
        }
    
        return attrList;
    }
    

    Die Klasse für das LibraryDocAttribute sieht dabei so aus:

    using System;
    
    [AttributeUsage( AttributeTargets.Method, AllowMultiple = false )]
    public class LibraryDocAttribute : Attribute
    {
        public string Key { get; set; }
    
        public LibraryDocAttribute( string key )
        {
            this.Key = key;
        }
    }

    Der Aufruf zur Ermittlung der List<LibraryDoc> dann so:

    List<LibraryDocAttribute> attributes = this.GetCustomAttributes<LibraryDocAttribute>( this.GetType().Assembly );

    Die Erweiterungsmethode hat folgenden Aufbau:

    using System;
    
    namespace MeinNamespace
    {
        public static class Extensions
        {
            [LibraryDoc( "Hallo Welt" )]
            public static String MakeSomething( this String value )
            {
                return value;
            }
        }
    }

    Damit erhalte ich dann beim Aufruf genau ein Element in der attributes Liste mit dem entsprechenden Key.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 27. Juli 2017 08:18
    Moderator
  • Hallo Gerhard,

    bei deinem Code steigt der bereits weit vor der Ermittlung der Methoden aus (und dabei ist es egal, ob ich das Attribut auf einer Instanz- oder einer statischen Methode anwende). Daher denke ich mal, dass das Problem mit deinem Code nichts mit statisch oder nicht statisch zu tun hat.

    if( type.IsPublic == true && type.GetCustomAttributes( typeof( TValue ), true ).Length > 0 )

    sorgt (zumindest in meiner Testanwendung) dafür, dass die Schleife aussteigt, da es keine Klasse gibt, die das LibraryDoc Attribut verwendet. In deinem Fall ist das wohl genauso.

    Zudem rufst Du die identische Methode zweimal auf, was letztendlich eine schlechtere Performance zur Folge hat.

    Einmal eben:

    if( type.IsPublic == true && type.GetCustomAttributes( typeof( TValue ), true ).Length > 0 )

    und direkt dahinter nochmal:

    dynamic attr = type.GetCustomAttributes( typeof( TValue ), true )

    Macht natürlich wenig Sinn.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Donnerstag, 27. Juli 2017 08:41
    Moderator
  • Hallo Stefan,

    wirklich sehr doof von mir.

    Das ist mir jetzt auch aufgefallen. Was ich mir das wohl gedacht haben ???
    Jedenfalls habe ich in Summe mit der ganzen Aktion einiges über Reflection und Attribute gelernt.

    Danke und Gruß
    Gehard

    Donnerstag, 27. Juli 2017 08:57