Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Para diseñar atributos personalizados, no es necesario aprender muchos conceptos nuevos. Si está familiarizado con la programación orientada a objetos y sabe cómo diseñar clases, ya tiene la mayoría de los conocimientos necesarios. Los atributos personalizados son clases tradicionales que derivan directa o indirectamente de la System.Attribute clase . Al igual que las clases tradicionales, los atributos personalizados contienen métodos que almacenan y recuperan datos.
Los pasos principales para diseñar correctamente clases de atributos personalizados son los siguientes:
En esta sección se describe cada uno de estos pasos y se concluye con un ejemplo de atributo personalizado.
Aplicación de "AttributeUsageAttribute"
Una declaración de atributo personalizado comienza con el System.AttributeUsageAttribute atributo , que define algunas de las características clave de la clase de atributo. Por ejemplo, puede especificar si el atributo se puede heredar por otras clases o a qué elementos se puede aplicar el atributo. En el fragmento de código siguiente se muestra cómo usar :AttributeUsageAttribute
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
<AttributeUsage(AttributeTargets.All, Inherited:=False, AllowMultiple:=True)>
Public Class SomeClass
Inherits Attribute
'...
End Class
AttributeUsageAttribute tiene tres miembros importantes para la creación de atributos personalizados: AttributeTargets, Inherited y AllowMultiple.
AttributeTargets (miembro)
En el ejemplo anterior, AttributeTargets.All se especifica , que indica que este atributo se puede aplicar a todos los elementos del programa. Como alternativa, puede especificar AttributeTargets.Class, que indica que el atributo solo se puede aplicar a una clase o AttributeTargets.Method, lo que indica que el atributo solo se puede aplicar a un método . Todos los elementos del programa se pueden marcar para su descripción mediante un atributo personalizado de esta manera.
También puede pasar varios AttributeTargets valores. El fragmento de código siguiente especifica que se puede aplicar un atributo personalizado a cualquier clase o método:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method)>
Public Class SomeOtherClass
Inherits Attribute
'...
End Class
Propiedad heredada
La AttributeUsageAttribute.Inherited propiedad indica si el atributo se puede heredar por clases derivadas de las clases a las que se aplica el atributo. Esta propiedad acepta una marca true
(por defecto) o una marca false
. En el ejemplo siguiente, MyAttribute
tiene un valor predeterminado Inherited de true
, mientras YourAttribute
que tiene un Inherited valor de false
:
// This defaults to Inherited = true.
public class MyAttribute : Attribute
{
//...
}
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
//...
}
' This defaults to Inherited = true.
Public Class MyAttribute
Inherits Attribute
'...
End Class
<AttributeUsage(AttributeTargets.Method, Inherited:=False)>
Public Class YourAttribute
Inherits Attribute
'...
End Class
A continuación, los dos atributos se aplican a un método de la clase MyClass
base :
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
//...
}
}
Public Class MeClass
<MyAttribute>
<YourAttribute>
Public Overridable Sub MyMethod()
'...
End Sub
End Class
Por último, la clase YourClass
se hereda de la clase MyClass
base . El método MyMethod
muestra MyAttribute
pero no YourAttribute
:
public class YourClass : MyClass
{
// MyMethod will have MyAttribute but not YourAttribute.
public override void MyMethod()
{
//...
}
}
Public Class YourClass
Inherits MeClass
' MyMethod will have MyAttribute but not YourAttribute.
Public Overrides Sub MyMethod()
'...
End Sub
End Class
AllowMultiple (propiedad)
La AttributeUsageAttribute.AllowMultiple propiedad indica si pueden existir varias instancias del atributo en un elemento . Si se establece en true
, se permiten varias instancias. Si se establece en false
(valor predeterminado), solo se permite una instancia.
En el ejemplo siguiente, MyAttribute
tiene un valor predeterminado AllowMultiple de false
, mientras YourAttribute
que tiene un valor de true
:
//This defaults to AllowMultiple = false.
public class MyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
' This defaults to AllowMultiple = false.
Public Class MyAttribute
Inherits Attribute
End Class
<AttributeUsage(AttributeTargets.Method, AllowMultiple:=true)>
Public Class YourAttribute
Inherits Attribute
End Class
Cuando se aplican varias instancias de estos atributos, MyAttribute
se produce un error del compilador. En el ejemplo de código siguiente se muestra el uso válido de YourAttribute
y el uso no válido de MyAttribute
:
public class MyClass
{
// This produces an error.
// Duplicates are not allowed.
[MyAttribute]
[MyAttribute]
public void MyMethod()
{
//...
}
// This is valid.
[YourAttribute]
[YourAttribute]
public void YourMethod()
{
//...
}
}
Public Class MyClass
' This produces an error.
' Duplicates are not allowed.
<MyAttribute>
<MyAttribute>
Public Sub MyMethod()
'...
End Sub
' This is valid.
<YourAttribute>
<YourAttribute>
Public Sub YourMethod()
'...
End Sub
End Class
Si tanto la AllowMultiple propiedad como la Inherited propiedad se establecen al true
, una clase que se hereda de otra clase puede heredar un atributo y tener otra vez el mismo atributo aplicado en la misma clase hija. Si AllowMultiple se establece en false
, los valores de los atributos de la clase padre se sobrescribirán por nuevas instancias del mismo atributo en la clase hija.
Declaración de la clase de atributo
Después de aplicar el AttributeUsageAttribute, empiece a definir los detalles de su atributo. La declaración de una clase de atributo es similar a la declaración de una clase tradicional, como se muestra en el código siguiente:
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
// . . .
}
<AttributeUsage(AttributeTargets.Method)>
Public Class MyAttribute
Inherits Attribute
' . . .
End Class
Esta definición de atributo muestra los siguientes puntos:
Las clases de atributo deben declararse como clases públicas.
Por convención, el nombre de la clase de atributo termina con la palabra Attribute. Aunque no es necesario, esta convención se recomienda para mejorar la legibilidad. Cuando se aplica el atributo, la inclusión de la palabra Attribute es opcional.
Todas las clases de atributo deben heredar directa o indirectamente de la System.Attribute clase .
En Microsoft Visual Basic, todas las clases de atributos personalizados deben tener el System.AttributeUsageAttribute atributo .
Declarar constructores
Al igual que las clases tradicionales, los atributos se inicializan con constructores. En el fragmento de código siguiente se muestra un constructor de atributos típico. Este constructor público toma un parámetro y establece una variable miembro igual a su valor.
public MyAttribute(bool myvalue)
{
this.myvalue = myvalue;
}
Public Sub New(myvalue As Boolean)
Me.myvalue = myvalue
End Sub
Puede sobrecargar el constructor para dar cabida a diferentes combinaciones de valores. Si también define una propiedad para la clase de atributo personalizada, puede usar una combinación de parámetros con nombre y posicional al inicializar el atributo. Normalmente, se definen todos los parámetros necesarios como posicionales y todos los parámetros opcionales como denominados. En este caso, el atributo no se puede inicializar sin el parámetro necesario. Todos los demás parámetros son opcionales.
Nota:
En Visual Basic, los constructores de una clase de atributo no deben usar un ParamArray
argumento .
En el ejemplo de código siguiente se muestra cómo se puede aplicar un atributo que usa el constructor anterior mediante parámetros opcionales y obligatorios. Se supone que el atributo tiene un valor booleano necesario y una propiedad de cadena opcional.
// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public class SomeClass
{
//...
}
// One required (positional) parameter is applied.
[MyAttribute(false)]
public class SomeOtherClass
{
//...
}
' One required (positional) and one optional (named) parameter are applied.
<MyAttribute(false, OptionalParameter:="optional data")>
Public Class SomeClass
'...
End Class
' One required (positional) parameter is applied.
<MyAttribute(false)>
Public Class SomeOtherClass
'...
End Class
Declarar propiedades
Si desea definir un parámetro con nombre o proporcionar una manera sencilla de devolver los valores almacenados por el atributo, declare una propiedad. Las propiedades de atributo deben declararse como entidades públicas con una descripción del tipo de datos que se devolverá. Defina la variable que contendrá el valor de su propiedad y asígnela a los métodos get
y set
. En el ejemplo de código siguiente se muestra cómo implementar una propiedad en el atributo :
public bool MyProperty
{
get {return this.myvalue;}
set {this.myvalue = value;}
}
Public Property MyProperty As Boolean
Get
Return Me.myvalue
End Get
Set
Me.myvalue = Value
End Set
End Property
Ejemplo de atributo personalizado
En esta sección se incorpora la información anterior y se muestra cómo diseñar un atributo que documente información sobre el autor de una sección de código. El atributo de este ejemplo almacena el nombre y el nivel del programador y si se ha revisado el código. Usa tres variables privadas para almacenar los valores reales que se van a guardar. Cada variable se representa mediante una propiedad pública que obtiene y establece los valores. Por último, el constructor se define con dos parámetros necesarios:
[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : Attribute
{
// Private fields.
private string name;
private string level;
private bool reviewed;
// This constructor defines two required parameters: name and level.
public DeveloperAttribute(string name, string level)
{
this.name = name;
this.level = level;
this.reviewed = false;
}
// Define Name property.
// This is a read-only attribute.
public virtual string Name
{
get {return name;}
}
// Define Level property.
// This is a read-only attribute.
public virtual string Level
{
get {return level;}
}
// Define Reviewed property.
// This is a read/write attribute.
public virtual bool Reviewed
{
get {return reviewed;}
set {reviewed = value;}
}
}
<AttributeUsage(AttributeTargets.All)>
Public Class DeveloperAttribute
Inherits Attribute
' Private fields.
Private myname As String
Private mylevel As String
Private myreviewed As Boolean
' This constructor defines two required parameters: name and level.
Public Sub New(name As String, level As String)
Me.myname = name
Me.mylevel = level
Me.myreviewed = False
End Sub
' Define Name property.
' This is a read-only attribute.
Public Overridable ReadOnly Property Name() As String
Get
Return myname
End Get
End Property
' Define Level property.
' This is a read-only attribute.
Public Overridable ReadOnly Property Level() As String
Get
Return mylevel
End Get
End Property
' Define Reviewed property.
' This is a read/write attribute.
Public Overridable Property Reviewed() As Boolean
Get
Return myreviewed
End Get
Set
myreviewed = value
End Set
End Property
End Class
Puede aplicar este atributo mediante el nombre completo, DeveloperAttribute
, o mediante el nombre abreviado, Developer
, de una de las maneras siguientes:
[Developer("Joan Smith", "1")]
-or-
[Developer("Joan Smith", "1", Reviewed = true)]
<Developer("Joan Smith", "1")>
-or-
<Developer("Joan Smith", "1", Reviewed := true)>
En el primer ejemplo se muestra el atributo aplicado solo con los parámetros con nombre necesarios. En el segundo ejemplo se muestra el atributo aplicado con los parámetros obligatorios y opcionales.