2009-06-20 12 views
11

Tengo un atributo personalizado que se aplica a las propiedades de clase y a la clase en sí. Ahora todas las clases que deben aplicar mi atributo personalizado se derivan de una sola clase base.Restringir atributo personalizado para que se pueda aplicar solo a tipos específicos en C#?

¿Cómo puedo restringir mi Atributo personalizado para que se pueda aplicar solo a esas clases, que deben derivar de mi clase base? ¿Cómo hago esto?

+0

¿Desea forzarlo (para que se complete automáticamente) o restringirlo (para que no pueda aplicarse a otros tipos)? –

+0

Quiero restringirlo para que no se pueda aplicar a tipos distintos a los no derivados de mi clase base. –

+0

Edit: ¡maldición, creo que me contradiqué al encontrar una manera de hacerlo! Una nueva para mí ... –

Respuesta

15

Darn, odio cuando demuestre mi mal ... funciona si se define el atributo como un protegida tipo anidado de la clase base:

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; } 
} 

(respuesta original)

No puede hacer esto, al menos, no en tiempo de compilación.

Los atributos se pueden restringir (por ejemplo) a "clase", "estructura", "método", "campo", etc., pero nada más granular.

Por supuesto, dado que los atributos no hacen nada por sí mismos (ignorando PostSharp), serán inertes en otros tipos (e inertes en sus tipos a menos que agregue algún código para ver los atributos en tiempo de ejecución).

Puede escribir una regla FxCop, pero eso parece exagerado.

Me pregunto, sin embargo, si un atributo es la mejor opción:

Ahora todas las clases que se deben aplicar mi atributo personalizado se derivan de una sola clase base.

Si deben aplicar su atributo personalizado, tal vez una abstract (o tal vez sólo virtual) Propiedad/método sería una mejor opción?

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

gracias marc. Estoy aplicando atributos a las propiedades para el mapeo. La clase base tiene un método que devuelve todas las propiedades en la clase derivada a la que se le aplica este atributo. Además, no hay ningún significado que permita que un atributo se aplique a cualquier tipo o miembro sin un propósito importante. –

+0

Incluso no encontré ninguna documentación para hacer esto, así que antes de llegar a alguna conclusión, quería darle una oportunidad con stackoverflow. Creo que los atributos se aplican a propósito, entonces, ¿por qué permitir que se apliquen a ese tipo o miembros que no tienen el propósito? –

+0

"Entonces, ¿por qué permitirlo?", Simplemente, no puede evitarlo en este momento. No hay un mecanismo para desautorizarlo. –

0

No tengo conocimiento de ninguna forma de hacerlo con los atributos personalizados.
Una mejor manera sería la de obtener las clases para implementar una interfaz con una restricción genérica

por lo

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

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

entonces su clase base haría esto

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

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

De esa manera el compilador imponer la restricción en tiempo de compilación para que solo las clases
derivadas de MyBaseClass puedan implementar la interfaz.
me hizo muy extensible mediante la definición de una clase MyAttribute pero podría, por supuesto, simplemente devolver una cadena o una bool si necesitaba algo más simple

que también hizo el miembro MyAttribute privado para que las clases derivadas no podían verlo y cámbielo pero podría protegerlo y permitir el acceso a clases derivadas si así lo desea.

Cuestiones relacionadas