Beschränken Sie benutzerdefinierte Attribute, so dass es nur auf bestimmte Typen in C # angewendet werden kann?

StackOverflow https://stackoverflow.com/questions/1021190

  •  06-07-2019
  •  | 
  •  

Frage

Ich habe ein benutzerdefiniertes Attribut, das auf Klasseneigenschaften und die Klasse selbst aufgebracht wird. Nun sind alle Klassen, die meine benutzerdefinierte Attribute gelten muss von einer einzigen Basisklasse abgeleitet werden.

Wie kann ich meine Custom Attribute beschränken, so dass es diese Klassen angewandt werden kann, um nur, die aus meiner Basisklasse ableiten müssen? Wie mache ich das?

War es hilfreich?

Lösung

Darn, ich hasse es, wenn ich mich falsch erweisen ... es funktioniert, wenn Sie das Attribut als geschützt verschachtelter Typ der Basisklasse definieren:

abstract class MyBase {
    [AttributeUsage(AttributeTargets.Property)]
    protected sealed class SpecialAttribute : Attribute {}
}

class ShouldBeValid : MyBase {
    [Special]
    public int Foo { get; set; }
}
class ShouldBeInvalid {
    [Special] // type or namespace not found
    [MyBase.Special] // inaccessible due to protection level
    public int Bar{ get; set; }
}

(original Antwort)

Sie können dies nicht tun - zumindest nicht bei der Kompilierung

.

Attribute können (für exmaple) beschränkt auf "Klasse", "Struktur", "Methode", "Feld", etc. -. Aber nichts mehr granulare

Natürlich, da Attribute nichts tun, indem sie sich selbst (ohne Berücksichtigung von Postsharp), werden sie auf andere Arten inert sein (und inert auf Typen, wenn Sie einige Code hinzufügen zu den Attributen zur Laufzeit sehen).

Sie könnten eine FxCop Regel schreiben, aber das scheint übertrieben.

Ich frage mich jedoch, ob ein Attribut ist die beste Wahl:

  

Nun sind alle Klassen, die meine benutzerdefinierte Attribute gelten muss von einer einzigen Basisklasse abgeleitet werden.

Wenn sie muss anwenden, um Ihr benutzerdefiniertes Attribut, vielleicht eine abstract (oder vielleicht auch nur virtual) Eigenschaft / Methode wäre eine bessere Wahl sein?

abstract class MyBase {
    protected abstract string GetSomeMagicValue {get;}
}
class MyActualType : MyBase {
    protected override string GetSomeMagicValue {get {return "Foo";}}
}

Andere Tipps

Ich bin von keiner Weise bewusst, dies zu tun mit benutzerdefinierten Attributen.
Eine bessere Möglichkeit wäre es, die Klassen zu bekommen eine Schnittstelle mit einer allgemeinen Einschränkung zu implementieren

so

class MyAttribute
{
     // put whatever custom data you want in here
}

interface IAttributeService<T> where T : MyBaseClass
{
     MyAttribute Value{get;}
}

dann Ihre Basisklasse würde dies tun

class MyBaseClass : IAttributeService<MyBaseClass>
{
     private MyAttribute m_attrib;

     IAttributeService<MyClass>.Value
     {
         get {return m_attrib;}
     }
}

Auf diese Weise der Compiler die Einschränkung bei der Kompilierung erzwingen wird, so dass nur Klassen
abgeleitet von MyBaseClass können die Schnittstelle implementieren.
Ich habe es ziemlich erweiterbar durch eine MyAttribute Klasse definieren, aber man kann natürlich nur einen String oder eine bool zurück, wenn Sie etwas einfacher erforderlich

Ich habe auch die MyAttribute Mitglied privat, so dass abgeleitete Klassen es nicht und es ändern sehen konnten, konnten es aber geschützt machen und abgeleiteten Klassen Zugriff erlauben, wenn man will.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top