Laden...

Kann "GetCustomAttributes" (Reflection) Attribute der Konkreten- und der Basisklasse finden?

Letzter Beitrag vor 7 Jahren 2 Posts 1.132 Views
Kann "GetCustomAttributes" (Reflection) Attribute der Konkreten- und der Basisklasse finden?

Hallo zusammen,

ich wollte mir gerade das Auslesen von Attributen über die Methode GetCustomAttributes genauer ansehen und sehen, wie der Parameter inherit richtig verwendet wird, Dabei bin ich über folgende Fälle gestolpert, die ich eigentlich anders erwartet hätte:


[MyAttribute("BaseClass")]
public class BaseClass { }

[MyAttribute("ChildClass")]
public class ChildClass : BaseClass { }

wenn ich hier über die ChildClass die Attribute abrufe wird mit Parameter inherit = true nur das Attribut gefunden, dass bei der ChildClass verwendet wurde. Das Attribut über BaseClass wird nicht gefunden.

typeof(ChildClass).GetCustomAttributes(true);

Ich hätte hier eigentlich erwartet, dass beide Attribute gefunden werden. Verstehe ich das falsch? Gibt es vielleicht auch eine Möglichkeit, dass man beide Attribute findet?

Der zweite Fall hat mich dann richtig stutzig gemacht:


[MyAttribute("IBaseInterface")]
public interface IBaseInterface { }

public class ChildClass : IBaseInterface { }

wenn ich hier auf ChildClass die Attribute suche, wird gar nichts gefunden. Da hätte ich erwartet dass das Attribute von IBaseInterface gefunden wird.

typeof(ChildClass).GetCustomAttributes(true);

Wenn ich statt dem Interface eine Basisklasse verwende, wird das Attribut entsprechend gefunden. Von daher hätte ich das gleiche Verhalten auch erwartet, wenn ich stattdessen ein Interface verwende.

Warum schreibe ich das hier? In meinen Augen sind das zwei Fälle, über die man gerne mal stolpern könnte. Daher würde ich gerne versuchen, die Hintergründe zu verstehen, damit ich mir das leichter merken kann. Vielleicht hat da jemand ein paar Informationen dazu.

Also erstmal gibts eine Attribute Inheritance, die per default true ist.

Machst Du also


[AttributeUsage(Inherited = true)]
class MyAttribute: Attribute {}

[MyAttribute("BaseClass")]
public class BaseClass { }

public class ChildClass : BaseClass { }

dann wirkt sich MyAttribute auch auf die ChildClass aus.

Was Du hast, zusätzlich das Attribut an die ChildClass, führt dazu, dass der Attributswert überschrieben wird.
Willst Du das nicht, dann musst Du AllowMultiple auf true setzen, was es per default nicht ist.

[AttributeUsage(AllowMultiple= true)]
class MyAttribute: Attribute{}

Dass Du die Attribute eines Interfaces in einer implementierten Klasse per default nicht angezeigt bekommst, das ist ein korrektes Verhalten. C# unterstützt das in dieser Form einfach nicht. In der CLR verhalten sich Interfaces und Klassen anders. inherited != implemented.
Wie das aber genau in der CLR / ILcode ausschaus, müsste ich jetzt auch irgendwo nachschauen oder ausprobieren.
Aber ein Grund ist zB: was würdest Du zB. bei einer Klasse machen, die mehrere Interfaces implementieren?
U.a. deswegen muss in einer Implementierung das Attribut aktiv gesetzt werden.

Du kannst Dir aber selbst eine Abfrage mit Hilfe von Reflection schreiben.
typeof(ChildClass).GetInterfaces() liefert Dir entsprechendes und diese wiederum kannst Du einfach auf das Attribut abfragen. Da findeste sicherlich Snippets im weiten Web dazu.