Этой строкой определяется область применения нашего атрибута - первый параметр (AttributeTargets.All) говорит о том, что мы сможем применять наш атрибут TestAttribute к чему угодно, второй (Inherited=false) - что атрибут не будет наследоваться (т. е. если мы применим атрибут TestAttribute к некоторому классу, то у потомков этого класса атрибута TestAttribute не будет), третий (AllowMultiple = true) - что атрибут к каждому элементу может пременяться только один раз (заметим в скобках, что для определения области применения нашего пользовательского атрибута мы используем другой атрибут - AttributeUsage).
Далее мы определяем для нашего атрибута внутреннюю переменную name типа string и конструктор с параметром типа string. В конструкторе мы записываем значение в переменную name. Еще чуть ниже мы пишем в классе атрибута свойство только для чтения:
...
public virtual string Name
{
get
{
return name;
}
}
...
После создания класса атрибута мы применяем его к другому классу Test. Для этого мы должны создать экземпляр атрибута TestAttribute непосредственно перед классом Test:
...
[TestAttribute("Igor Alexeev")]class Test
{
...
Делаем мы это в квадратных скобках. При этом у нас вызывается конструктор с параметром атрибута.
В классе Test мы в методе GetAttribute просто выводим на консоль значение свойства name атрибута. Для этого мы воспользовались статическим методом GetCustomAttribute класса Attribute. Этот метод принимает в качестве параметров тип, к которому атрибут применяется (т. е. класс Test в нашем случае) и собственно атрибут, который мы применяем (у нас это TestAttribute). Возвращает же он экземпляр атрибута, который мы и используем для получения значения свойства name.
Метод GetAttribute мы вызываем в констукторе класса Test.
Результатом выполнения нашей программы будет вывод на консоль слов "Igor Alexeev".