Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Для разработки пользовательских атрибутов вам не нужно изучать множество новых концепций. Если вы знакомы с объектно-ориентированным программированием и знаете, как разрабатывать классы, у вас уже есть большая часть необходимых знаний. Пользовательские атрибуты — это традиционные классы, которые прямо или косвенно являются производными от System.Attribute класса. Как и традиционные классы, пользовательские атрибуты содержат методы, которые хранят и извлекают данные.
Ниже приведены основные шаги по правильному проектированию пользовательских классов атрибутов:
В этом разделе описывается каждый из этих шагов и завершается примером пользовательского атрибута.
Применение атрибута AttributeUsageAttribute
Объявление пользовательского атрибута начинается с System.AttributeUsageAttribute атрибута, который определяет некоторые ключевые характеристики класса атрибутов. Например, можно указать, можно ли наследовать атрибут другими классами или к каким элементам можно применить атрибут. В следующем фрагменте кода показано, как использовать AttributeUsageAttribute.
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
<AttributeUsage(AttributeTargets.All, Inherited:=False, AllowMultiple:=True)>
Public Class SomeClass
Inherits Attribute
'...
End Class
AttributeUsageAttribute имеет три члена, важные для создания пользовательских атрибутов: AttributeTargets, Inherited, и AllowMultiple.
Член AttributeTargets
В предыдущем примере указывается, AttributeTargets.All что этот атрибут можно применить ко всем элементам программы. Кроме того, можно указать AttributeTargets.Class, указывая, что атрибут может применяться только к классу или AttributeTargets.Method, указывая, что атрибут можно применять только к методу. Все элементы программы можно пометить для описания пользовательским атрибутом таким образом.
Можно также передать несколько AttributeTargets значений. Следующий фрагмент кода указывает, что настраиваемый атрибут можно применить к любому классу или методу:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method)>
Public Class SomeOtherClass
Inherits Attribute
'...
End Class
Унаследованное свойство
Свойство AttributeUsageAttribute.Inherited указывает, может ли атрибут наследоваться классами, производными от классов, к которым применяется атрибут. Это свойство принимает либо значение true
(по умолчанию), либо флаг false
. В следующем примере MyAttribute
имеет значение по умолчанию Inherited, а true
имеет YourAttribute
значение Inherited:
// 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
Затем два атрибута применяются к методу в базовом классе MyClass
:
public class MyClass
{
[MyAttribute]
[YourAttribute]
public virtual void MyMethod()
{
//...
}
}
Public Class MeClass
<MyAttribute>
<YourAttribute>
Public Overridable Sub MyMethod()
'...
End Sub
End Class
Наконец, класс YourClass
наследуется от базового класса MyClass
.
MyMethod
Метод показываетMyAttribute
, но не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
Свойство AttributeUsageAttribute.AllowMultiple указывает, может ли существовать несколько экземпляров атрибута в элементе. Если задано значение true
, допускается несколько экземпляров. Если задано значение false
(по умолчанию), допускается только один экземпляр.
В следующем примере MyAttribute
имеет значение по умолчанию AllowMultiple, а false
имеет значение YourAttribute
.
//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
При применении MyAttribute
нескольких экземпляров этих атрибутов возникает ошибка компилятора. В следующем примере кода показано допустимое использование и недопустимое использование YourAttribute
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
AllowMultiple Если для свойства и Inherited свойства задано true
значение, класс, унаследованный от другого класса, может наследовать атрибут и иметь другой экземпляр одного и того же атрибута, примененного в одном дочернем классе. Если AllowMultiple задано значение false
, значения любых атрибутов в родительском классе будут перезаписаны новыми экземплярами одного и того же атрибута в дочернем классе.
Объявление класса атрибутов
После применения этого AttributeUsageAttributeпараметра начните определять особенности атрибута. Объявление класса атрибутов похоже на объявление традиционного класса, как показано в следующем коде:
[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
// . . .
}
<AttributeUsage(AttributeTargets.Method)>
Public Class MyAttribute
Inherits Attribute
' . . .
End Class
Это определение атрибута демонстрирует следующие моменты:
Классы атрибутов должны быть объявлены как общедоступные классы.
По соглашению имя класса атрибута заканчивается словом Attribute. Хотя это не обязательно, это соглашение рекомендуется для удобочитаемости. При применении атрибута добавление слова Attribute является необязательным.
Все классы атрибутов должны наследоваться напрямую или косвенно от System.Attribute класса.
В Microsoft Visual Basic все пользовательские классы атрибутов должны иметь System.AttributeUsageAttribute атрибут.
Объявление конструкторов
Как и традиционные классы, атрибуты инициализированы конструкторами. Следующий фрагмент кода иллюстрирует типичный конструктор атрибутов. Этот открытый конструктор принимает параметр и задает переменную-член, равную его значению.
public MyAttribute(bool myvalue)
{
this.myvalue = myvalue;
}
Public Sub New(myvalue As Boolean)
Me.myvalue = myvalue
End Sub
Конструктор можно перегрузить для размещения различных сочетаний значений. Если вы также определяете свойство для пользовательского класса атрибутов, при инициализации атрибута можно использовать сочетание именованных и позиционных параметров. Как правило, все необходимые параметры определяются как позиционные и все необязательные параметры как именованные. В этом случае атрибут не может быть инициализирован без обязательного параметра. Все остальные параметры являются необязательными.
Замечание
В Visual Basic конструкторы для класса атрибутов не должны использовать ParamArray
аргумент.
В следующем примере кода показано, как атрибут, использующий предыдущий конструктор, можно применить с помощью необязательных и обязательных параметров. Предполагается, что атрибут имеет одно необходимое логическое значение и одно необязательное строковое свойство.
// 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
Объявление свойств
Если вы хотите определить именованный параметр или предоставить простой способ возврата значений, хранящихся в атрибуте, объявите свойство. Свойства атрибута должны объявляться как общедоступные сущности с описанием возвращаемого типа данных. Определите переменную, которая будет содержать значение вашего свойства и связывать её между методами get
и set
. В следующем примере кода показано, как реализовать свойство в атрибуте:
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
Пример пользовательского атрибута
В этом разделе приведены предыдущие сведения и показано, как создать атрибут, который документирует сведения о авторе раздела кода. Атрибут в этом примере сохраняет имя и уровень программиста, а также проверяется ли код. Он использует три частных переменных для хранения фактических значений для сохранения. Каждая переменная представлена общедоступным свойством, которое получает и задает значения. Наконец, определён конструктор с двумя обязательными параметрами.
[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
Этот атрибут можно применить с помощью полного имени, DeveloperAttribute
, или с помощью сокращенного имени, Developer
, одним из следующих способов:
[Developer("Joan Smith", "1")]
-or-
[Developer("Joan Smith", "1", Reviewed = true)]
<Developer("Joan Smith", "1")>
-or-
<Developer("Joan Smith", "1", Reviewed := true)>
В первом примере показан атрибут, примененный только к обязательным именованным параметрам. Во втором примере показан атрибут, применяемый как с обязательными, так и необязательными параметрами.