2009-07-27 7 views
10

J'ai tenté de créer un attribut .NET personnalisé avec le code ci-dessous, mais je l'ai laissé par inadvertance dans la sous-classe. Cela a généré une erreur de compilation facilement corrigée dans le commentaire.Spécification de la classe de base requise pour les cibles d'attribut .NET

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

Ma question est de savoir comment le compilateur connaît l'attribut [AttributeUsage] ne peut être appliqué à une sous-classe de System.Attribute? Utilisation de .NET Reflector Je ne vois rien de spécial sur la déclaration de classe AttributeUsageAttribute elle-même. Malheureusement, cela pourrait être un cas spécial généré par le compilateur lui-même.

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

Je voudrais être en mesure de préciser que mon attribut personnalisé ne peut être placé sur les sous-classes d'une classe particulière (ou interface). Est-ce possible?

+0

Cette restriction est parfois un signe que vous devez utiliser un marqueur d'interface à la place. Il effectue les mêmes fonctions, sauf lorsque vous devez transmettre des métadonnées de niveau classe en tant que paramètre. Donc, si les instances peuvent tout aussi bien fournir say, un décompte de quelque chose, l'interface peut exiger qu'une propriété publique l'obtienne. Si cela doit être au niveau de la classe, vous êtes bloqué avec des attributs. –

Répondre

26

J'aimerais pouvoir spécifier que mon attribut personnalisé ne peut être placé que sur des sous-classes d'une classe (ou interface) particulière. Est-ce possible?

En fait, il y a une façon de le faire pour les sous-classes (mais pas les interfaces) en utilisant protected - voir Restricting Attribute Usage. Pour reproduire le code (mais pas la discussion):

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

Excellent merci! Pour être honnête, je n'ai jamais envisagé de le faire jusqu'à ce que j'obtienne l'erreur du compilateur mais je vais définitivement trouver votre solution. –

2

AttributeUsageAttribute est juste une classe magique (comme Attribute lui-même est). C'est une règle de compilation intégrée, et vous ne pouvez pas faire quelque chose comme ça pour vos propres attributs.

0

Avec ReSharper vous pouvez utiliser [JetBrains.Annotations.BaseTypeRequired(typeof(YouBaseType))]

Questions connexes