2009-07-27 6 views
10

Ho tentato di creare un attributo .NET personalizzato con il codice riportato di seguito, ma per sbaglio ho lasciato la sottoclasse. Questo ha generato un errore del compilatore facilmente risolto mostrato nel commento.Specificare la classe di base richiesta per gli attributi degli obiettivi .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() 
    { 
    } 
} 

La mia domanda è come fa il compilatore conosce l'attributo [AttributeUsage] può essere applicato solo ad una sottoclasse di System.Attribute? Utilizzo di .NET Reflector Non vedo nulla di speciale nella dichiarazione della classe AttributeUsageAttribute. Sfortunatamente questo potrebbe essere solo un caso speciale generato dal compilatore stesso.

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

Mi piacerebbe essere in grado di specificare che il mio attributo personalizzato può essere posizionato solo su sottoclassi di una particolare classe (o interfaccia). È possibile?

+0

Questa limitazione a volte è un segno che si deve usare un interfaccia marcatore invece. Esegue le stesse funzioni, tranne quando è necessario passare i metadati a livello di classe come parametro. Quindi, se le istanze possono altrettanto facilmente dire, un conteggio di qualcosa, l'interfaccia può richiedere una proprietà pubblica per ottenerlo. Se deve essere di classe, sei bloccato con gli attributi. –

risposta

26

Vorrei essere in grado di specificare che il mio attributo personalizzato può essere inserito solo in sottoclassi di una particolare classe (o interfaccia). È possibile?

In realtà, c'è un modo per fare questo per le sottoclassi (ma non interfacce) che utilizzano protected - vedi Restricting Attribute Usage. Per riprodurre il codice (ma non la discussione):

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

Eccellente grazie! Ad essere onesti non ho mai pensato di farlo fino a quando non ho ottenuto l'errore del compilatore, ma sicuramente la tua soluzione. –

2

AttributeUsageAttribute è solo una classe magica (come lo è Attribute). Questa è una regola del compilatore incorporata e non puoi fare qualcosa del genere per i tuoi attributi.

0

Con ReSharper si può usare [JetBrains.Annotations.BaseTypeRequired(typeof(YouBaseType))]

Problemi correlati