Перфолента.NET. ООП. Атрибуты элементов программы — различия между версиями

Материал из ТХАБ.РФ
Перейти к: навигация, поиск
м (Применение атрибутов)
м (Применение атрибутов)
 
(не показано 13 промежуточных версий 2 участников)
Строка 1: Строка 1:
В языке [[Перфолента.Net]] можно привязать к элементам программы дополнительную информацию, которая придаст им дополнительный смысл, особое назначение или особые правила использования. У атрибута нет логики, он просто хранит несколько параметров, что бы их можно было прочитать в будущем. Практический смысл создавать атрибуты есть тогда, когда есть необходимость из другой программы анализировать элементы текущей.  
+
В языке [[Перфолента.Net]] можно привязать к элементам программы (модулям, полям, функциям) дополнительную информацию, которая придаст им дополнительный смысл, особое назначение или особые правила использования. У атрибута нет логики, он просто хранит несколько значений, что бы их можно было прочитать в будущем. Практический смысл создавать атрибуты есть тогда, когда есть необходимость из другой программы анализировать элементы текущей.  
 +
 
 +
Фактически '''Атрибут - это метка''' которую можно прикрепить к полю, функции, методу, самой программе (сборке) или модулю программы (DLL) значение которой сможет прочитать другой компонент этой или другой программы:
 +
 
 +
Значение присвоенное атрибуту '''ИмяАтрибута''' процедуры '''ИмяПроцедуры''' сможет прочитать любая программа, которая обратится к программе содержащей процедуру '''ИмяПроцедуры''' т.е. внешняя программа прочитав значение атрибута ИмяАтрибута у процедуры ИмяПроцедуры получит значение "ЗачениеАтрибута" которое сможет использовать по своему усмотрению.
 +
 +
• [[Перфолента.NET. ООП. Как написать свой атрибут|Как написать свой атрибут]]
  
 
В языке Перфолента, как и в других .Net языках, атрибуты элементов программы используются:
 
В языке Перфолента, как и в других .Net языках, атрибуты элементов программы используются:
Строка 6: Строка 12:
 
Это значит, что как компилятор может внести изменения в генерируемый машинный код основываясь на атрибутах, так и выполняющаяся программа может менять своё поведение в зависимости от атрибутов выполняемого кода.
 
Это значит, что как компилятор может внести изменения в генерируемый машинный код основываясь на атрибутах, так и выполняющаяся программа может менять своё поведение в зависимости от атрибутов выполняемого кода.
  
Процесс получения атрибутов сборки и других элементов программы называется рефлексией (reflection).
+
Процесс '''получения''' атрибутов сборки и других элементов программы называется рефлексией (reflection).
  
 
== Виды атрибутов ==
 
== Виды атрибутов ==
Строка 13: Строка 19:
 
* выполнение кода программы
 
* выполнение кода программы
  
Атрибуты могут быть определены:
+
Атрибуты определены:
 
* в библиотеке Net Framework и могут использоваться компиляторами любых .Net языков
 
* в библиотеке Net Framework и могут использоваться компиляторами любых .Net языков
 
* в стандартной библиотеке Перфоленты и могут использоваться компилятором Перфоленты и программами, использующими эту библиотеку  
 
* в стандартной библиотеке Перфоленты и могут использоваться компилятором Перфоленты и программами, использующими эту библиотеку  
Строка 27: Строка 33:
  
 
== Применение атрибутов ==
 
== Применение атрибутов ==
=== Для  указания области видимости полей ===
+
Наиболее популярные и простые в использовании атрибуты:
* &ВидноВсем - к переменной, полю, функции, методу - могут обращаться другие объекты
 
* ОбщийДляКласса - [[Поле]] существует в 1-м экземпляре, для всех объектов данного типа (Класса)
 
  
Примеры использования  
+
* [[&ВидноВсем]] -  атрибуты видимости классов и их членов, к полю, функции, методу, объекту - могут обращаться другие объекты
 +
* [[&ОбщийДляКласса]] - [[Поле]] существует в 1-м экземпляре, для всех объектов данного типа (Класса)
 +
* [[&ТолькоЧтение]], [[&ТолькоЗапись]] - атрибуты ограничения доступа к полям и свойствам объекта
 +
* [[&ИмпортМетода]] – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру
 +
 
 +
Примеры использования:
 
  Класс Лампа  
 
  Класс Лампа  
 
         // Поля класса  
 
         // Поля класса  
         &ВидноВсем Поле Состояние тип Строка = "Выключена" // Переменная  
+
         &ВидноВсем
 +
        Поле Состояние тип Строка = "Выключена" // Переменная имеющая атрибут &ВидноВсем
  
 
     &ВидноВсем
 
     &ВидноВсем
     Функция ИмяФункции  
+
     Функция ИмяФункции // Функция имеющая атрибут &ВидноВсем
 
       ----
 
       ----
 
     КонецФункции
 
     КонецФункции
 
== Написание собственного атрибута и его использование ==
 
 
У атрибута нет логики, он просто хранит несколько параметров, что бы их можно было прочитать в будущем.
 
 
Например, Атрибут - '''АнглийскийСиноним''' может использоваться компилятором, если пользователь вдруг решил писать код на английском языке, тогда компилятор будет искать метод не только по именам, но и по синонимам.
 
 
В стандартной библиотеке Перфоленты почти для всех классов и их членов определены английские синонимы, но компилятор пока ими не умеет ими пользоваться (зарезервировано на будущее)
 
 
Практический смысл создавать атрибуты есть тогда, когда есть необходимость из другой программы анализировать элементы текущей.
 
 
Например:
 
* редактор формы может показывать в палитре свойств только те свойства формы у которых буде установлен атрибут '''РедактируетсяВПалитреСвойств''' или не будет атрибута '''УстаревшееСвойство'''
 
 
* Программа тестирования может запускать только те методы у которых установлен атрибут '''Тестировать'''.
 
 
* Программа выгрузки класса может выгружать только те поля у которых есть атрибут '''Выгружать''' и т.д. применений можно много найти...
 
 
Определим простейший атрибут '''АнглийскийСиноним''':
 
 
&ВидноВсем
 
Класс АнглийскийСиноним Родитель Атрибут
 
        Поле _Синоним тип Строка
 
        &ВидноВсем
 
        Конструктор(Синоним тип Строка)
 
                _Синоним = Синоним
 
        КонецКонструктора
 
        &ВидноВсем
 
        Функция ПолучитьСиноним() тип Строка
 
                Возврат _Синоним
 
        КонецФункции
 
КонецКласса
 
 
Как видим, кроме наследования от типа Атрибут, других особенностей у класса-атрибута нет.
 
 
Используем созданный нами атрибут АнглийскийСиноним для одного из методов программы - Процедуры Старт:
 
 
&АнглийскийСиноним("Start"), ВидноВсем
 
Процедура Старт
 
        //тут какой-то код
 
КонецПроцедуры
 
 
Мы задали для процедуры Старт два атрибута, один созданный нами - '''АнглийскийСиноним''', а другой встроенный - '''ВидноВсем'''.
 
 
'''АнглийскийCиноним''' процедуры Старт сможет узнать любая программа (в том числе и эта), которая захочет исследовать сборку программы содержащей процедуру т.е. внешняя программа прочитав значение атрибута АнглийскийСиноним у процедуры Старт получит значение "Start" которое сможет использовать по своему усмотрению.
 
 
Во время компиляции создается экземпляр объект указанного класса-атрибута и сохраняется в сборке в области метаданных вместе с элементом программы, который отмечен этим атрибутом. Любой код, который использует сборку может восстановить экземпляр объекта-атрибута и узнать значения его полей и свойств, получая необходимую дополнительную информацию об элементе программы, который был отмечен этим атрибутом.
 
Список атрибутов располагается перед элементом программы, к которому он принадлежит, начинается с символа & и разделяется запятыми:
 
 
&Атрибут1, Атрибут2, АтрибутН  ЭлементПрограммы...
 
 
Для удобства чтения кода обычно ЭлементПрограммы располагают на новой строке вот так:
 
 
&Атрибут1, Атрибут2, АтрибутН
 
ЭлементПрограммы...
 
 
Каждый отдельный атрибут — это экземпляр объект указанного класса, созданный оператором Новый, с последующим заполнением полей и свойств этого созданного объекта инициализатором, если необходимо.
 
 
В конструктор атрибута можно передать необходимое количество параметров:
 
 
&Новый ContextClass("МойКласс", "MyClass")
 
Ключевое слово Новый при создании атрибутов не обязательно, просто помните, что оно там присутствует неявно:
 
 
&ContextClass("МойКласс", "MyClass")
 
 
После вызова конструктора можно заполнить значения полей и свойств атрибута с помощью инициализатора:
 
 
&Новый ИмпортМетода("kernel32.dll") { .EntryPoint="SetConsoleTitleW", .CharSet=CharSet.Auto, .SetLastError=True}
 
 
Значениями параметров конструктора, полей и свойств могут быть только константные не изменяемые  в дальнейшем выражения, вычисляемые при компиляции.
 
 
//в этом атрибуте проверим вычисление константных выражений в параметрах
 
&EnumerationType("Виды"+"Операци"+"и"с,  "Operation"+"Types",  Не Ложь)
 
 
Для встроенных атрибутов, например, таких, как атрибуты видимости членов, можно использовать стандартный синтаксис, но смысла в этом нет:
 
 
&Новый ВидноВсем(){}, Новый ВидноСборке(){}
 
 
Пустые круглые и фигурные скобки, как и ключевое слово Новый не обязательны:
 
 
&ВидноВсем, ВидноСборке
 
  
 
== Встроенные атрибуты языка Перфолента ==
 
== Встроенные атрибуты языка Перфолента ==
Строка 126: Строка 55:
 
В язык Перфолента встроены следующие атрибуты:
 
В язык Перфолента встроены следующие атрибуты:
  
* '''ВидноВсем''', '''ВидноСборке''', '''ВидноНаследникам''', '''ВидноНаследникамСборки''' - атрибуты видимости классов и их членов;
+
* '''ВидноВсем''', '''ВидноСборке''', '''ВидноНаследникам''', '''ВидноНаследникамСборки''' - атрибуты видимости классов и их членов
  
* '''ПространствоИмен'''("МоёПространство "), ПространствоИмён("МоёПространство") (синонимы) - атрибут класса, определяющий пространство имен, к которому принадлежит класс;
+
* '''ПространствоИмен'''("МоёПространство "), ПространствоИмён("МоёПространство") (синонимы) - атрибут класса, определяющий пространство имен, к которому принадлежит класс
  
* '''ОднопоточнаяМодель''', '''МногопоточнаяМодель''' - атрибуты метода Старт, определяющие модель взаимодействия для COM объектов;
+
* '''ОднопоточнаяМодель''', '''МногопоточнаяМодель''' - атрибуты метода Старт, определяющие модель взаимодействия для COM объектов
  
* '''ОбщийДляКласса''' - атрибут члена класса (Поля, Метода) делающий его общим для всех созданных экземпляров объектов этого класса;
+
* '''ОбщийДляКласса''' - атрибут члена класса (Поля, Метода) делающий его общим для всех созданных экземпляров объектов этого класса
  
* '''Глобальный''' - атрибут модуля, определяющий доступ всех видимых ко всем видимым членам модуля из всех других методов программы
+
* '''Глобальный''' - атрибут модуля, определяющий доступ всех видимых ко всем видимым членам модуля из всех других методов программы
  
 
* '''Сериализуемый''' – атрибут класса, указывающий компилятору необходимость создать код поддержки сериализации данных класса; ссылка в вики на сериализация класса
 
* '''Сериализуемый''' – атрибут класса, указывающий компилятору необходимость создать код поддержки сериализации данных класса; ссылка в вики на сериализация класса
  
* '''ДолженНаследоваться''', '''МожетНаследоваться''', '''НеМожетНаследоваться''' - атрибуты класса, определяющие возможность или необходимость его наследования;
+
* '''ДолженНаследоваться''', '''МожетНаследоваться''', '''НеМожетНаследоваться''' - атрибуты класса, определяющие возможность или необходимость его наследования
  
* '''ДолженПереопределяться''', '''МожетПереопределяться''', '''НеМожетПереопределяться''' - атрибуты члена класса (Поле, Метод,), определяющие возможность или необходимость его переопределения;
+
* '''ДолженПереопределяться''', '''МожетПереопределяться''', '''НеМожетПереопределяться''' - атрибуты члена класса (Поле, Метод,), определяющие возможность или необходимость его переопределения
  
* '''Переопределение''' - атрибут переопределения метода родителя в классе-наследнике;
+
* '''Переопределение''' - атрибут переопределения метода родителя в классе-наследнике
  
* '''Перекрытие''' - атрибут перекрытия метода родителя в классе-наследнике;
+
* '''Перекрытие''' - атрибут перекрытия метода родителя в классе-наследнике
  
* '''Перегрузка''' - атрибут перегрузки методов с одинаковыми именами;
+
* '''Перегрузка''' - атрибут перегрузки методов с одинаковыми именами
  
* '''ТолькоЧтение''', '''ТолькоЗапись''' - атрибуты ограничения доступа к полям и свойствам;
+
* '''ТолькоЧтение''', '''ТолькоЗапись''' - атрибуты ограничения доступа к полям и свойствам
  
* '''Обработчик'''("МоёСобытие") - атрибут метода класса (процедуры), определяющий, что метод является обработчиком указанного события;
+
* '''Обработчик'''("МоёСобытие") - атрибут метода класса (процедуры), определяющий, что метод является обработчиком указанного события
  
* '''ИмпортМетода''' – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру;
+
* '''ИмпортМетода''' – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру
  
 
Назначение и особенности использования встроенных атрибутов подробнее рассматриваются в тех статьях, где описаны сущности языка, к которым  
 
Назначение и особенности использования встроенных атрибутов подробнее рассматриваются в тех статьях, где описаны сущности языка, к которым  
 
применяются конкретные атрибуты
 
применяются конкретные атрибуты
  
== Атрибуты NET Framework и их использование ==
+
== См. также  ==
+
* [[Перфолента.NET. ООП. Атрибуты Net Farmework]]
=== Атрибуты сборки (.NET) ===
+
* [[Перфолента.NET. ООП. Как написать свой атрибут]]
В .Net определены разнообразные атрибуты, которые есть смысл применять к сборке в определенных ситуациях. Этот вид атрибутов желательно задавать в начале программы на уровне классов.
 
 
АтрибутСборки  System.Runtime.InteropServices.ComVisible(Ложь)
 
 
=== Атрибуты модуля сборки (.NET) ===
 
В .Net определены несколько атрибутов, которые есть смысл применять к модулю сборки в определенных ситуациях (не путайте модуль сборки с модулями программы). Этот вид атрибутов желательно задавать в начале программы на уровне классов.
 
 
 
АтрибутМодуля  System.CLSCompliant(Истина)
 
 
 
=== Атрибуты параметров метода. ===
 
 
 
Не только сами методы могут иметь атрибуты, но и их параметры. Для параметров используется тот же синтаксис атрибутов, как и для других элементов программы.
 
 
 
&ВидноВсем
 
Функция СобратьБит32( &АнглСиноним("HighDigits") Знач СтаршиеРазряды тип Бит16,
 
                      &АнглСиноним("LowDigits")  Знач МладшиеРазряды тип Бит16
 
                      ) &АнглСиноним("ReturnValue") тип Бит32 //к возвращаемому параметру тоже можно применить атрибуты
 
    Возврат (Бит32(СтаршиеРазряды) << 16) БитИли МладшиеРазряды
 
КонецФункции
 
 
=== Определение особого порядка и правил передачи полей структуры (NET)===
 
 
 
Структуры, которые необходимо передавать коду, написанному на языках подобных C, C++, Rust, чаще всего необходимо отметить атрибутом StructLayout заставляющем среду исполнения сформировать структуру пригодную к передаче. Также необходимо убедиться, что правильно передаются поля имеющие сложный тип, такие как массивы или другие структуры. Для задания правил передачи используется атрибут MarshalAs. Ознакомьтесь с документацией .Net по этим атрибутам, прежде, чем передавать структуры в код, написанный на указанных языках.
 
 
 
&StructLayout(LayoutKind.Sequential){ .Pack=1, .CharSet=CharSet.Auto }
 
Структура UDT
 
    &ВидноВсем Поле rxStatus тип Цел16
 
    &ВидноВсем Поле datalen тип Байт
 
 
 
    &ВидноВсем, MarshalAs(UnmanagedType.ByValArray){ .SizeConst=255 }
 
    Поле array1 тип Байт[]
 
 
 
    &ВидноВсем
 
    Процедура Инициализировать()
 
        //код инициализации
 
    КонецПроцедуры
 
 
 
КонецСтруктуры
 
 
=== Наиболее актуальные случаи применения атрибутов (NET)===
 
# Пометить метод атрибутом WebMethod в Web сервисах, для указания, что метод должен вызываться через SOAP протокол.
 
# Описание способа передачи параметров метода в не управляемый код с помощью атрибута System.Runtime.InteropServices.MarshalAs.
 
# Описание свойств COM для классов, методов и интерфейсов.
 
# Вызов методов неуправляемого кода с помощью атрибута System.Runtime.InteropServices.DllImport (синоним ИмпортМетода).
 
# Описание свойств сборки, таких как, версия, заголовок, копирайт и т.д., с помощью группы атрибутов подобных System.Reflection.AssemblyTitle.
 
# Пометка членов класса, которые могут быть сериализованы с помощью атрибута System.Serializable (синоним Сериализуемый).
 
# Описание сопоставления между членами класса и узлами XML для сериализации объекта в XML.
 
# Описание требований безопасности для методов.
 
# Указание характеристик, используемых для обеспечения безопасности.
 
# Установка параметров JIT компиляции, например, для сохранения удобства отладки.
 
# Получение информации о вызывающем методе.
 
# Указание на то, что метод или другой элемент программы устарел с помощью атрибута System.Obsolete.
 
 
 
Использование атрибутов в указанных случаях описано в документации .Net.
 
 
 
== Устройство атрибута ==
 
 
 
Технически, атрибуты — это специальные классы, унаследованные от класса Атрибут, который в .Net соответствует классу System.Attribute.
 
Атрибуты могут что-то значить сами по себе или иметь конструктор, принимающий на хранение дополнительную информацию в виде параметров.  Типы параметров конструктора атрибута, а также полей и свойств, ограничены в .Net следующими типами:
 
Цел8, Цел32, Цел64, Байт, Бит32, Бит64, Вещ, ДВещ, Строка, Символ, Булево, Тип,
 
а также это может быть Перечисление одного из указанных типов.
 
 
 
К сожалению, платформа .Net не поддерживает тип Дата в качестве параметра атрибута, но при необходимости дату (как и другие сериализуемые типы) можно представлять строкой.
 
  
 +
== Ссылки ==
 +
* http://promcod.com.ua/Article.asp?code=20201106234710055491 Первоисточник
  
 
[[Категория:Перфолента.NET. Описание языка Перфолента.NET]]
 
[[Категория:Перфолента.NET. Описание языка Перфолента.NET]]
 
[[Категория:Перфолента.NET. Объектно-Ориентированное Программирование]]
 
[[Категория:Перфолента.NET. Объектно-Ориентированное Программирование]]

Текущая версия на 19:38, 12 ноября 2020

В языке Перфолента.Net можно привязать к элементам программы (модулям, полям, функциям) дополнительную информацию, которая придаст им дополнительный смысл, особое назначение или особые правила использования. У атрибута нет логики, он просто хранит несколько значений, что бы их можно было прочитать в будущем. Практический смысл создавать атрибуты есть тогда, когда есть необходимость из другой программы анализировать элементы текущей.

Фактически Атрибут - это метка которую можно прикрепить к полю, функции, методу, самой программе (сборке) или модулю программы (DLL) значение которой сможет прочитать другой компонент этой или другой программы:

Значение присвоенное атрибуту ИмяАтрибута процедуры ИмяПроцедуры сможет прочитать любая программа, которая обратится к программе содержащей процедуру ИмяПроцедуры т.е. внешняя программа прочитав значение атрибута ИмяАтрибута у процедуры ИмяПроцедуры получит значение "ЗачениеАтрибута" которое сможет использовать по своему усмотрению.

Как написать свой атрибут

В языке Перфолента, как и в других .Net языках, атрибуты элементов программы используются:

  • на стадии компиляции
  • на стадии выполнения

Это значит, что как компилятор может внести изменения в генерируемый машинный код основываясь на атрибутах, так и выполняющаяся программа может менять своё поведение в зависимости от атрибутов выполняемого кода.

Процесс получения атрибутов сборки и других элементов программы называется рефлексией (reflection).

Виды атрибутов

Итак, Атрибуты могут влиять на:

  • сборку (компиляцию) программы
  • выполнение кода программы

Атрибуты определены:

  • в библиотеке Net Framework и могут использоваться компиляторами любых .Net языков
  • в стандартной библиотеке Перфоленты и могут использоваться компилятором Перфоленты и программами, использующими эту библиотеку
  • Вами в вашей программе и использовать их будете только Вы

Часть используемых вами атрибутов определена прямо в языке Перфолента (в стандартной библиотеке), это:

  • видимости (ВидноВсем),
  • наследования,
  • переопределения методов
  • и другие (ТолькоДляЧтения).

Важно: в языке 1С, как и в некоторых других языках программирования, атрибуты называют аннотациями. В разных языках синтаксис записи атрибутов (аннотаций) различен, как и способы их использования, но в большинстве современных языков они в том или ином виде есть.

Применение атрибутов

Наиболее популярные и простые в использовании атрибуты:

  • &ВидноВсем - атрибуты видимости классов и их членов, к полю, функции, методу, объекту - могут обращаться другие объекты
  • &ОбщийДляКласса - Поле существует в 1-м экземпляре, для всех объектов данного типа (Класса)
  • &ТолькоЧтение, &ТолькоЗапись - атрибуты ограничения доступа к полям и свойствам объекта
  • &ИмпортМетода – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру

Примеры использования:

Класс Лампа 
        // Поля класса 
        &ВидноВсем
        Поле Состояние тип Строка = "Выключена" // Переменная имеющая атрибут &ВидноВсем
   &ВидноВсем
   Функция ИмяФункции // Функция имеющая атрибут &ВидноВсем
     ----
   КонецФункции

Встроенные атрибуты языка Перфолента

В язык Перфолента встроены следующие атрибуты:

  • ВидноВсем, ВидноСборке, ВидноНаследникам, ВидноНаследникамСборки - атрибуты видимости классов и их членов
  • ПространствоИмен("МоёПространство "), ПространствоИмён("МоёПространство") (синонимы) - атрибут класса, определяющий пространство имен, к которому принадлежит класс
  • ОднопоточнаяМодель, МногопоточнаяМодель - атрибуты метода Старт, определяющие модель взаимодействия для COM объектов
  • ОбщийДляКласса - атрибут члена класса (Поля, Метода) делающий его общим для всех созданных экземпляров объектов этого класса
  • Глобальный - атрибут модуля, определяющий доступ всех видимых ко всем видимым членам модуля из всех других методов программы
  • Сериализуемый – атрибут класса, указывающий компилятору необходимость создать код поддержки сериализации данных класса; ссылка в вики на сериализация класса
  • ДолженНаследоваться, МожетНаследоваться, НеМожетНаследоваться - атрибуты класса, определяющие возможность или необходимость его наследования
  • ДолженПереопределяться, МожетПереопределяться, НеМожетПереопределяться - атрибуты члена класса (Поле, Метод,), определяющие возможность или необходимость его переопределения
  • Переопределение - атрибут переопределения метода родителя в классе-наследнике
  • Перекрытие - атрибут перекрытия метода родителя в классе-наследнике
  • Перегрузка - атрибут перегрузки методов с одинаковыми именами
  • ТолькоЧтение, ТолькоЗапись - атрибуты ограничения доступа к полям и свойствам
  • Обработчик("МоёСобытие") - атрибут метода класса (процедуры), определяющий, что метод является обработчиком указанного события
  • ИмпортМетода – специальный атрибут метода, указывающий компилятору, что реализация метода находится во внешней библиотеке и имеет указанную сигнатуру

Назначение и особенности использования встроенных атрибутов подробнее рассматриваются в тех статьях, где описаны сущности языка, к которым применяются конкретные атрибуты

См. также

Ссылки