2009-07-27 5 views
10

Ich habe versucht, ein benutzerdefiniertes .NET-Attribut mit dem folgenden Code zu erstellen, aber versehentlich die Unterklasse verlassen. Dies führte zu einem leicht zu korrigierenden Compilerfehler, der im Kommentar angezeigt wurde.Angeben der erforderlichen Basisklasse für .NET-Attributziele

// results in compiler error CS0641: Attribute 'AttributeUsage' is 
// only valid on classes derived from System.Attribute 
[AttributeUsage(AttributeTargets.Class)] 
internal class ToolDeclarationAttribute 
{ 
    internal ToolDeclarationAttribute() 
    { 
    } 
} 

Meine Frage ist, wie funktioniert der Compiler weiß, dass das [AttributeUsage] Attribut kann nur auf eine Unterklasse von System.Attribute angewendet werden? .NET Reflector verwenden Ich sehe nichts besonderes auf der Klassen-Deklaration AttributeUsageAttribute. Leider könnte dies ein spezieller Fall sein, der vom Compiler selbst generiert wird.

[Serializable, ComVisible(true), AttributeUsage(AttributeTargets.Class, Inherited=true)] 
public sealed class AttributeUsageAttribute : Attribute 
{ 
    ... 

Ich mag wäre in der Lage sein, dass meine benutzerdefinierten Attribute angeben, nur auf Subklassen einer bestimmten Klasse platziert werden (oder Schnittstelle). Ist das möglich?

+0

Diese Einschränkung verwenden, ist manchmal ein Zeichen sollten Sie stattdessen einen Marker-Schnittstelle verwenden. Es führt die gleichen Funktionen aus, außer wenn Sie Metadaten auf Klassenebene als Parameter übergeben müssen. Also, wenn Instanzen können genauso einfach sagen, eine Zählung von etwas, kann die Schnittstelle eine öffentliche Eigenschaft verlangen, dass. Wenn es auf Klassenebene sein muss, bleiben Sie bei den Attributen stecken. –

Antwort

26

Ich möchte in der Lage sein, anzugeben, dass mein benutzerdefiniertes Attribut nur auf Unterklassen einer bestimmten Klasse (oder Schnittstelle) platziert werden kann. Ist das möglich?

Eigentlich gibt es eine Möglichkeit, dies für Unterklassen zu tun (aber nicht Schnittstellen) mit protected - siehe Restricting Attribute Usage. Um den Code zu reproduzieren (aber nicht die Diskussion):

abstract class MyBase { 
    [AttributeUsage(AttributeTargets.Property)] 
    protected sealed class SpecialAttribute : Attribute {} 
} 
class ShouldBeValid : MyBase { 
    [Special] // works fine 
    public int Foo { get; set; } 
} 
class ShouldBeInvalid { // not a subclass of MyBase 
    [Special] // type or namespace not found 
    [MyBase.Special] // inaccessible due to protection level 
    public int Bar{ get; set; } 
} 
+0

Ausgezeichnet danke! Um ehrlich zu sein, habe ich nie darüber nachgedacht, das zu tun, bis ich den Compilerfehler habe, aber ich werde definitiv deine Lösung finden. –

2

AttributeUsageAttribute ist nur eine magische Klasse (wie Attribute selbst ist). Dies ist eine integrierte Compiler-Regel, und Sie können so etwas für Ihre eigenen Attribute nicht tun.

0

Mit ReSharper können Sie [JetBrains.Annotations.BaseTypeRequired(typeof(YouBaseType))]