Запись атрибутов что это
Четыре вида метаданных NTFS
В данной теме я рассмотрю четыре вида метаданных, которые могут быть прикреплены к файлу или каталогу средствами файловой системы NTFS. Я опишу, в каких целях можно использовать тот или иной тип метаданных, приведу пример его применения в какой-либо технологии Microsoft или стороннем программном обеспечении.
Речь пойдёт о точках повторной обработки (reparse points), идентификаторах объектов (object id) и о других типах данных, которые может содержать файл помимо своего основного содержимого.
Object Id
Идентификатор объекта это 64 байта, которые можно прикрепить к файлу или каталогу. Из них первые 16 байт позволяют однозначно идентифицировать файл в пределах тома и обращаться к нему не по имени, а по идентификатору. Остальные 48 байт могут содержать произвольные данные.
Идентификаторы объектов существуют в NTFS со времён Windows 2000. В самой системе они используются для отслеживания расположения файла, на который ссылается ярлык (.lnk). Допустим, файл, на который ссылается ярлык, был перемещён в пределах тома. При запуске ярлыка он всё равно откроется. Специальная служба Windows в случае, если файл не найден, произведёт попытку открыть файл не по его имени, а по заранее созданному и сохранённому идентификатору. Если файл не был удалён и не покидал пределы тома, он откроется, а ярлык снова будет указывать на файл.
Идентификаторы объектов использовались в технологии iSwift Антивируса Касперского 7-ой версии. Вот как описана эта технология: Технология разработана для файловой системы NTFS. В этой системе каждому объекту присваевается NTFS-индентификатор. Этот индентификатор сравнивается с значениями специальной базы данных iSwift. Если значения базы данных с NTFS-индентификатором не совпадают, то объект проверяется или перепроверяется, если он был изменен.
Впрочем, переизбыток созданных идентификаторов вызывал проблемы со сканированием диска стандартной утилитой проверки chkdsk, она происходила слишком долго. В следующих версиях Антивируса Касперского отказались от использования NTFS Object Id.
Reparse Point
В файловой системе NTFS файл или каталог может содержать в себе reparse point, что переводится на русский язык как «точка повторной обработки». В файл или каталог добавляются специальные данные, файл перестаёт быть обычным файлом и обработать его может только специальный драйвер фильтра файловой системы.
В Windows присутствуют типы reparse point, которые могут быть обработаны самой системой. Например, через точки повторной обработки в Windows реализуются символьные ссылки (symlink) и соединения (junction point), а также точки монтирования томов в каталог (mount points).
Reparse-буфер, присоединяемый к файлу это буфер, имеющий максимальный размер 16 килобайт. Он характеризуется наличием тега, который говорит системе о том, к какому типу принадлежит точка повторной обработки. При использовании reparse-буфера собственного типа ещё необходимо задавать в нём GUID в специальном поле, а в reparse-буферах Microsoft он может отсутствовать.
Какие типы точек повторной обработки существуют? Перечислю технологии, в которых используются reparse point’ы. Это Single Instance Storage (SIS) и Cluster Shared Volumes в Windows Storage Server 2008 R2, Hierarchical Storage Management, Distributed File System (DFS), Windows Home Server Drive Extender. Это технологии Microsoft, здесь не упомянуты технологии сторонних компаний, использующие точки повторной обработки, хотя такие тоже есть.
Extended Attributes
Расширенные атрибуты файла. Про них был мой предыдущий топик. Здесь стоит упомянуть только то, что под Windows эта технология практически не применяется. Из известного мне программного обеспечения только Cygwin использует расширенные атрибуты для хранения POSIX прав доступа. У одного файла на NTFS могут быть или расширенные атрибуты, или буфер точки повторной обработки. Одновременная установка и того и другого невозможна. Максимальный размер всех расширенных атрибутов у одного файла составляет 64 Кб.
Alternate Data Streams
Дополнительные файловые потоки. Про них знает уже, наверное, каждый. Перечислю основные признаки этого вида метаданных: именованность (то есть у файла может быть несколько потоков, и у каждого своё имя), прямой доступ из файловой системы (их можно открывать, используя формат «имя файла, двоеточие, имя потока»), неограниченный размер, возможность запуска процесса прямо из потока (и возможность реализовать через это бесфайловый процесс).
Использовались в технологии iStream Антивируса Касперского. Используются в самой Windows, например при скачивании файла из интернета к нему прицепляется поток Zone.Identifier, содержащий информацию о том, из какого места получен данный файл. После запуска исполняемого файла пользователь может увидеть сообщение «Не удаётся проверить издателя. Вы действительно хотите запустить эту программу?».
Так пользователю даётся дополнительная защита от необдуманного запуска программ, полученных из интернета. Это лишь одно применение потоков, а так в них можно хранить самые разные данные. Упомянутый Антивирус Касперского хранил там контрольные суммы каждого файла, но позже от этой технологии тоже по какой-то причине отказались.
Что-нибудь ещё?
Есть ещё идентификатор безопасности, плюс стандартные атрибуты файла, к которым нет прямого доступа, несмотря на то, что они тоже реализованы как потоки файлов. И они, и расширенные атрибуты, и reparse и object id — всё это потоки файла с точки зрения системы. Напрямую изменять идентификатор безопасности, показанный на следующей картинке как ::$SECURITY_DESCRIPTOR смысла нет, пусть его изменением занимается система. К другим типам потоков сама система не даёт прямого доступа. Так что на этом всё.
Просмотр содержимого object id, точек повторной обработки, а также работа с расширенными атрибутами и альтернативными файловыми потоками возможна с помощью программы NTFS Stream Explorer, а также через системную консольную утилиту fsutil.
Разрешения NTFS
Под разрешением NTFS понимается правило, связанное с объектом (файлом, папкой) и используемое для управления доступом пользователей к этому объекту. При этом под пользователем понимается не только пользователь-человек как таковой, но и программы, запущенные от его имени (под его учетной записью).
Стандартные разрешения
Разрешения для папок имеют ту особенность, что они определяют возможные действия как для самих папок, так и для содержащихся внутри них файлов и подпапок. Ниже в таблице показано, что это могут быть за разрешения.
Стандартные разрешения NTFS для папок:
Разрешение | Допускаемые действия |
---|---|
Чтение (Read) | Разрешается просматривать вложенные папки и файлы, а также их свойства: имя владельца, разрешения и атрибуты (такие как «только чтение», «скрытый», «архивный» и «системный») |
Запись (Write) | Разрешается создавать и размещать внутри папки новые файлы и подпапки, а также изменять атрибуты папки и просматривать ее свойства: владельца и разрешения |
Список содержимого папки (List folder contents) | Дает право просматривать имена содержащихся в папке файлов и вложенных подпапок |
Чтение и выполнение (Read&Execute) | Позволяет получить доступ к файлам в подпапках, даже если нет доступа к самой папке. Кроме того разрешает те же действия, что предусмотрены для разрешений «Чтение» и «Список содержимого папки» |
Изменение (Modify) | Разрешает все действия, предусмотренные для разрешений «Чтение» и «Чтение и выполнение» + разрешает удаление папки |
Полный доступ (Full control) | Предоставляет полный доступ к папке. Это значит, что допускаются все действия, предусмотренные всеми перечисленными выше разрешениями. Дополнительно позволя- ется становиться владельцем папки и изменять ее разрешения |
Особые Permission) | Задает набор специальных разрешений, отличающийся от стандартных и перечисленных ниже |
Разрешения для файлов имеют те же названия, но смысл их несколько отличается.
Стандартные разрешения NTFS для файлов:
Разрешение | Допускаемые действия |
---|---|
Чтение (Read) | Разрешается чтение файла, а также просмотр его свойств: имя владельца, разрешений и атрибутов |
Запись (Write) | Разрешается перезапись файла, изменение его атрибутов, а также просмотр его владельца и разрешений |
Чтение и выполнение (Read&Execute) | То же что и «Чтение» + возможность запуска приложения (если файл исполняемый) |
Изменение (Modify) | Допускает изменение и удаление файла + то, что предусмотрено разрешениями «Запись» и «Чтение и выполнение» |
Полный доступ (Full control) | Предоставляет полный доступ к файлу. Это значит, что допускаются все действия, предусмотренные всеми перечис- ленными выше разрешениями. Дополнительно позволяется становиться владельцем файла и изменять его разрешения |
Особые Permission) | Задает набор специальных разрешений, отличающийся от стандартных и перечисленных ниже |
Специальные разрешения
Если стандартные разрешения предназначены для общих случаев, для быстрого и удобного назначения прав доступа, то специализированные права доступа позволяют подойти к этому делу более ответственно.
При этом можно изменить стандартный набор разрешений так, как будет необходимо. Описание специализированных разрешений как для папок, так и для файлов показано в таблице ниже.
Специальные разрешения NTFS для файлов и папок:
Разрешение | Описание |
---|---|
Обзор папок / Выполнение файлов | Для папок. Разрешение «Обзор папок» позволяет или запрещает перемещение по структуре папок в поисках других файлов или папок. Причем это допускается даже в тех случаях, когда пользователь не обладает разрешением на доступ к просматриваемым папкам. Для разрешения «Обзор папок» имеется одно ограничение: оно действительно только в том случае, если группа или пользователь не обладает правом «Обход перекрестной проверки», устанавливаемым в оснастке «Групповая политика». (По умолчанию правом «Обход перекрестной проверки» наделена группа «Все»). Для файлов. Разрешение «Выполнение файлов» позволяет или |
Содержание папки / Чтение данных | Для папок. Разрешение «Содержание папки» позволяет или запрещает просмотр имен файлов и подпапок, содержащихся в папке. Это разрешение относится только к содержимому данной папки и не означает, что имя самой этой папки также должно включаться в список. Для файлов. Разрешение «Чтение данных» позволяет или |
Чтение атрибутов | Разрешает или запрещает просмотр таких атрибутов файла или папки, как «Только чтение» и «Скрытый» |
Чтение атрибутов | Разрешает или запрещает просмотр дополнительных атрибутов файла или папки. Дополнительные атрибуты определяются программами и могут различаться для разных программ |
Создание файлов / Запись данных | Для папок. Разрешение «Создание файлов» позволяет или запрещает создание файлов в папке (применимо только к папкам). Для файлов. Разрешение «Запись данных» позволяет или. запрещает внесение изменений в файл и запись поверх имеющегося содержимого |
Создание папок / Дозапись данных | Для папок. Разрешение «Создание папок» позволяет или запрещает создание папок внутри папки (применимо только к папкам). Для файлов. Разрешение «Дозапись данных» позволяет или запрещает внесение данных в конец файла, но не изменение, удаление или замену имеющихся данных (применимо только к файлам) |
Запись атрибутов | Разрешает или запрещает смену таких атрибутов файла или папки, как «Только чтение» и «Скрытый». При этом разрешение «Запись атрибутов» не подразумевает права на создание или удаление файлов или папок: разрешается только вносить изменения в их атрибуты |
Запись дополнительных атрибутов | Разрешает или запрещает смену дополнительных атрибутов файла или папки. Дополнительные атрибуты определяются программами и могут различаться для разных программ. Разрешение «Запись дополнительных атрибутов» не подразумевает права на создание или удаление файлов или папок: разрешается только вносить изменения в их атрибуты |
Удаление | Разрешает или запрещает удаление файла или папки. Если для файла или папки отсутствует разрешение «Удаление», то объект все же можно удалить при наличии разрешения «Удаление подпапок и файлов» для родительской папки |
Удаление подпапок и файлов | Это разрешение применяется только к папкам. Оно позволяет или запрещает удаление подпапок и файлов внутри папки даже в тех случаях, когда отсутствует разрешение «Удаление» |
Чтение разрешений | Разрешает или запрещает чтение разрешений на доступ к файлу или папке (т.е. разрешений «Полный доступ», «Чтение» и «Запись») |
Смена разрешений | Разрешает или запрещает смену разрешений на доступ к файлу или папке (таких как «Полный доступ», «Чтение» и «Запись») |
Смена владельца | Разрешает или запрещает вступать во владение файлом или папкой. Привилегия владельца состоит в том, что он всегда может изменять разрешения на доступ к файлу или папке, независимо от любых разрешений, защищающих этот файл или папку |
Синхронизация | При одновременном доступе к одним и тем же папкам (файлам) данное разрешение позволяет или запрещает ожидание различными потоками файлов или папок и синхронизацию их с другими потоками. Это разрешение применимо только к программам, выполняемым в многопоточном режиме с несколькими процессами |
Разрешения для файлов и папок
В таблице также можно увидеть, что стандартные разрешения «Список содержимого папки» и «Чтение и выполнение» включают в себя одинаковый перечень особых разрешений. Тем не менее разница все-таки есть, а заключается она в том, что наследуются эти разрешения по разному. Так, разрешение «Список содержимого папки» наследуется только папками и отображается только при просмотре разрешений на доступ к папкам. Файлами это разрешение не наследуется.
Что касается разрешения «Чтение и выполнение», то оно наследуется как папками, так и файлами. Отображается оно также при просмотре разрешений на доступ как к папкам, так и к файлам.
В этой связи следует отметить, что пользователи, которым разрешен полный доступ к папке, могут удалять любые файлы в этой папке, независимо от установленных для них разрешений.
Вхождение специальных разрешений в стандартные разрешения.
Атрибуты файла — какие бывают и как их изменить
Иногда по самым разным причинам пользователям ОС Windows требуется поменять некоторые атрибуты одного или нескольких файлов. В этой статье вы узнаете, как их менять. Скриншоты сделаны на ОС Windows 7, но во всех остальных версиях Windows принцип действия практически тот же.
Следует отметить, что наличие и принцип работы некоторых атрибутов файлов может зависеть от вашей файловой системы. В рядовых ситуациях с обычными, простенькими атрибутами, типо атрибутов скрытия или сжатия все просто. Посмотреть и поменять стандартные атрибуты файлов и его объем можно нажав на файле ПКМ и войдя в его «Свойства».
А теперь перейдем к более близкому знакомству с ними.
Какие бывают основные атрибуты файла?
В операционной системой Windows пользователи могут увидеть, что существует разделение на четыре основных типа. Познакомимся с этими видами атрибутов, которыми могут обладать любые файлы и, частично, папки.
Системный
Данный тип известен как «S». Этим атрибутом обычно помечаются системные папки с документами, программами и прочими важными файлами, в которые юзерам лучше всего не вмешиваться.
По этой причине пользователи не смогут увидеть эти объекты в Проводнике. Так что придется обеспечивать доступ к ним только после отключения опции, которая направлена на скрытие защищённых системных файлов. После ее активации можно будет увидеть все объекты. Но лучше все же этого не делать, чтобы не нанести урон процессам, отвечающим за работу операционной системы, а также многим прочим важным компонентам, от которых зависит функционирование устройства.
Для чтения
Атрибут «R» предполагает сохранение информации, которая в дальнейшем будет открываться исключительно для чтения.
Используется это с целью установки запрета правки текстовых файлов. Если пользователь частенько работает с информацией, а затем сохраняет ее на съемные накопители, то в таком случае можно просто защитить флешку от записи. Предварительно в корне данного накопителя нужно будет создать папку только для чтения.
Это неплохой вариант защиты от сторонних пользователей. Однако различные вирусы и прочие угрозы «умеют» обходить данные барьеры, чтобы проникать в файлы и просто заражать их. Так что при необходимости лучше всего частенько проверять данный накопитель на предмет выявления различных угроз.
Архивный
Необходимость использования данного типа атрибутов «А» заключается в том, чтобы создавать бэкапы. Так что нужен он для определенных утилит. Также пригодится для распознавания тех файлов, которые ранее были включены в резервную копию. Удается выявить и те объекты, которые ранее были скорректированы, а в настоящее время просто подлежат замене.
Скрытый
Скрытый атрибут «Н» помогает сделать объекты невидимыми, но при этом они не будут отмечаться в качестве системных. Пользователи, таким образом, могут попробовать скрыть любые файлы и папки, чтобы в дальнейшем в Проводнике они никак не отображались.
Другие атрибуты файлов
Но такая классификация известна пользователям, которые работали с прежними версиями данной операционной системы. Финальные версии данной платформы обладают еще некоторыми дополнительными объектами. Они совершенно не нуждаются в изменении, однако юзерам все же следует узнать о них как можно больше информации. Это зашифрованный, сжатый атрибут, а также представлены индексированный, временный и прочие.
В дополнение к этому предусмотрен вариант проведения работы с атрибутом целостности и проведения работы без предварительной очистки. Так что разнообразие таких элементов достаточно велико. Некоторые их перечисленных компонентов пользователь может увидеть в разделе со свойствами файлов.
Также к атрибутам можно отнести даже временные метки файла. Они помогают выяснить то, когда именно был создан документ, время его первого открытия и некоторых изменений. Благодаря столь точной информации пользователь может понять, как именно производилась работа с определенным объектом.
В системных файлах юзеры могут увидеть в обычном варианте только дату производимых корректировок. Чтобы получить доступ к более полной информации, необходимо открыть пункт со свойствами. В этом случае можно увидеть даты создания объекта, производимых в отношении его изменений.
При этом можно корректировать все эти данные. Если пользователь будет вносить правки, то все эти изменения моментально вступят в силу. В итоге и дата корректировки будет изменена в автоматическом режиме.
информация взята из статьи bezwindowsa.ru/moya-zhizn/osnovnyie-atributyi-faylov.html
Как изменить атрибуты файла в Windows?
В рядовых ситуациях с обычными, простенькими атрибутами, типо скрытия или сжатия все просто. Посмотреть и поменять их можно, нажав на файле ПКМ и войдя в его «Свойства».
Во вкладке «Общие» вы можете увидеть пункт «Атрибуты». Галочка на пункте «Только чтение» запретит системе и пользователям менять этот файл. Это может пригодиться в случае, если вы хотите отправить его кому-то, но не хотите, чтобы он его менял. Если выставить галочку на пункте «Скрытый», «Проводник» и похожие программы не будут его отображать.
Теперь нажмите кнопку «Дополнительно».
Здесь вы можете увидеть и заменить такие атрибуты, как индексирование, архивации, сжатия и шифрования. Если вкратце, сжатие делает файл менее «Весомым» (пока он не нужен, он находится в неком «спресованном» состоянии, когда его активируют, ОС сама его разворачивает, когда он прекращает свою работу или его закрывают, сжимает обратно). Шифрование — защита от утечки данных. Последнее — реально большая тема, советую почитать по-подробнее.
Как снять атрибуты «Скрытый» и «Системный»
Бывают ситуации, когда какой-нибудь вирус выставляет на файле атрибут «Системный», тем самым крайне усложняя работу с ним. В этом случае программа «Проводник» не будет его отображать. Если у вас именно эта проблема, прочтите нашу статью про то, как включить показ скрытых файлов и папок. Скриншоты там сделаны на Windows 10, но и в других более-менее новых версиях Windows алгоритм тот же.
Если вы хотите эти атрибуты именно снять, зайдите в командную строку от имени администратора. Если не знаете, как — пройдите по ссылке, там все подробно описано. Скриншоты сделаны на Windows 7, но по традиции, в других ОС Windows процесс выглядит так же.
Введите в командную строку команду «cd /D путь», где «путь» означает путь к папке, в которой расположен файл и нажмите «Enter». Путь проще будет скопировать. Вот статья про то, как копировать путь к папке на Windows 7.
В Total Commander
Для того, чтобы снять у файла атрибуты Скрытый, Системный с помощью файлового менеджера Total Commander:
Ошибка «Отказано в доступе» — решение проблемы
Решение для Windows XP
информация взята из статьи: sonikelf.ru/otkazano-v-dostupe-k-papke/
Вам будет интересно
Многие пользователи рано или поздно задумываются над безопасностью данных на компьютере. Особенно если оберегать их требуется…
Здравствуйте, дорогие посетители. Сегодня расскажу про изменение привычного внешнего вида курсора мыши на новый. Тема…
Приветствую Вас, друзья! Хочется поделиться с Вами своим маленьким секретом по работе в программе для…
Здравствуйте друзья! В этом статье я вам расскажу, как изменить язык в SonyVegaspro11, 12, и…
Атрибуты C#: обо всех аспектах
Здравствуй, читатель. В этой статье описаны атрибуты со всех сторон — начиная от спецификации, смысла и определения атрибутов, создания собственных и работе с ними, заканчивая добавлением атрибутов на рантайме и наиболее полезными и интересными существующими атрибутами. Если вам интересна тема атрибутов в C#, то добро пожаловать под кат.
Содержание
Введение
Как всегда, начнем с определений и спецификаций. Это поможет понять и осознать атрибуты на всех уровнях, что, в свою очередь, очень полезно для того, чтобы находить им правильные применения.
С синтаксической точки зрения (в метаданных) есть следующие атрибуты
Пример
Как видно StructLayoutAttribute имеет специальный синтаксис, так как в IL он представлен как «explicit». ObsoleteAttribute использует общий синтаксис — в IL начинается с «.custom». SecurityPermissionAttribute как атрибут безопасности превратился в «.permissionset assert».
Пользовательские атрибуты добавляют пользовательскую информацию к метаданным. Этот механизм может использоваться для хранения специфичной для приложения информации во время компиляции и для доступа к ней во время выполнения или для чтения и анализа другим инструментом. Хотя любой определенный пользователем тип может быть использован в качестве атрибута, для соответствия CLS необходимо, чтобы атрибуты наследовались от System.Attribute. CLI предопределяет некоторые атрибуты и использует их для управления поведением во время выполнения. Некоторые языки определяют атрибуты для представления возможностей языка, не представленных непосредственно в CTS.
Как уже упоминалось, атрибуты хранятся в метаданных, которые, в свою очередь, формируются на этапе компиляции, т.е. вносятся в PE файл (как правило *.dll). Таким образом, добавить во время выполнения атрибут можно только модифицируя исполняемый файл во время выполнения (но времена самоизменяющихся программ уже давно в прошлом). Отсюда следует, что на этапе выполнения их добавить нельзя, но это не совсем точно. В случае, если мы формируем свою сборку, определяем в ней типы, то мы можем на этапе выполнения создать новый тип и вешать атрибуты на него. Так что формально, мы все же можем добавлять атрибуты на этапе выполнения (пример будет в самом низу).
А теперь немного об ограничениях
Если по каким-то причинам в одной сборке существует 2 атрибута с именами Name и NameAtribute, то становится невозможным поставить первый из них. При использовании [Name] (т.е. без суффикса) компилятор говорит, что видит неопределенность. При использовании [NameAttribute] мы поставим NameAttribute, что логично. Для такой мистической ситуации с недостатком воображения при именовании существует специальный синтаксис. Чтобы поставить первую версию без суффикса можно указать знак собаки (т.е. [Name] — шутка, так не надо) перед именем атрибута [@Name].
Пользовательские атрибуты могут быть добавлены к чему угодно, кроме пользовательских атрибутов. Имеется в виду метаданные, т.е. если мы ставим в C# атрибут над классом атрибута, то в метаданных он будет относиться к классу. А вот добавить атрибут к «public» нельзя. Зато можно к сборкам, модулям, классам, типам значений, перечислениям (enum), конструкторам, методам, свойствам, полям, событиям, интерфейсам, параметрам, делегатам, возвращаемым значениям или обобщенным параметрам. В примере ниже приведены очевидные и не очень примеры того, как можно поставить атрибут на ту или иную конструкцию.
Атрибуты имеют 2 типа параметров — именованные и позиционные. К позиционным относятся параметры конструктора. К именованным — публичные свойства с доступным сеттером. При этом это не просто формальные названия, все параметры можно указывать при объявлении атрибута в скобках после его названия. Именованные не являются обязательными.
Допустимые параметры (обоих видов) для атрибута должны быть одного из перечисленных типов:
Существует два вида пользовательских атрибутов: подлинные пользовательские атрибуты (genuine custom attributes) и псевдо-пользовательские (pseudo-custom).
В коде они выглядят одинаково (указываются над конструкцией языка в квадратных скобках), но обрабатываются по-разному:
Большинство пользовательских атрибутов введены на уровне языка. Они хранятся и возвращаются рантаймом, при этом рантайм не знает ничего о значении этих атрибутов. Но все псевдо-пользовательские атрибуты плюс некоторые пользовательские атрибуты представляют особый интерес для компиляторов и для CLI. Таким образом мы переходим к следующему разделу.
Атрибуты с поддержкой рантайма
Данный раздел носит чисто информативный характер, если интереса к тому, что использует рантайм нет, то можно скролить к следующему разделу.
В таблице ниже перечислены псевдо-пользовательские атрибуты и специальные пользовательские атрибуты (CLI или компиляторы обрабатывают их специальным образом).
Псевдо-пользовательские атрибуты (их нельзя получить через рефлексию).
CLI Атрибуты:
Атрибут | Описание |
---|---|
AssemblyAlgorithmIDAttribute | Записывает идентификатор используемого алгоритма хеширования. Задает поле Assembly.HashAlgId |
AssemblyFlagsAttribute | Записывает флаги для соответствующей сборки. Задает поле Assembly.Flags |
DllImportAttribute | Предоставляет информацию о коде, реализованном в неуправляемой библиотеке. Устанавливает Method.Flags.PinvokeImpl бит соответствующего метода; добавляет новую запись в ImplMap (устанавливая значения MappingFlags, MemberForwarded, ImportName и ImportScope) |
StructLayoutAttribute | Позволяет явно задать способ размещения полей ссылочного или значимого типа. Устанавливает поле TypeDef.Flags.LayoutMask для типа. Также может устанавливать поля TypeDef.Flags.StringFormatMask, ClassLayout.PackingSize и ClassLayout.ClassSize |
FieldOffsetAttribute | Определяет смещение в байтах полей в ссылочном или значимом типе. Устанавливает значение FieldLayout.OffSet для соответствующего метода |
InAttribute | Показывает, что параметр передается как [in] аргумент. Устанавливает Param.Flags.In бит для соответствующего параметра |
OutAttribute | Показывает, что параметр передается как [out] аргумент. Устанавливает Param.Flags.Out бит для соответствующего параметра |
MarshalAsAttribute | Определяет способ маршалинга данных между управляемым и неуправляемым кодом. Устанавливает Field.Flags.HasFieldMarshal бит для поля (или Param.Flags.HasFieldMarshal бит для параметра); Добавляет запись в таблицу FieldMarshal (устанавливая значения Parent и NativeType) |
MethodImplAttribute | Определяет детали реализации метода. Устанавливает значение Method.ImplFlags для соответствующего метода |
CLS Атрибуты — языки должны поддерживать их:
Атрибут | Описание |
---|---|
AttributeUsageAttribute | Используется для указания, как атрибут может быть использован |
ObsoleteAttribute | Показывает, что элемент не должен использоваться |
CLSCompliantAttribute | Указывает, объявлен ли элемент как CLS-совместимый |
Атрибут | Описание |
---|---|
ThreadStaticAttribute | Предоставляет поля типа, относящиеся к потоку |
ConditionalAttribute | Помечает метод как вызываемый, опираясь на условие компиляции (указанное в /define). Если условие не соблюдено, то метод не вызовется (И не будет скомпилирован в IL). Может быть помечен только void метод. В противном случае возникнет ошибка компиляции |
DecimalConstantAttribute | Сохраняет значение константы типа decimal в метаданных |
DefaultMemberAttribute | Определяет член класса, который будет использоваться по умолчанию методом InvokeMember |
CompilationRelaxationsAttribute | Указывает, являются ли исключения из проверок инструкций строгими или смягченными. На текущий момент можно передать только параметр NoStringInterning, который помечает сборку как не требующую интернирования строковых литералов. Но этот механизм все еще может использоваться |
FlagsAttribute | Атрибут, указывающий, должен ли enum восприниматься как битовые флаги |
IndexerNameAttribute | Указывает имя, под которым индексатор будет известен в языках программирования, которые не поддерживают такую возможность напрямую |
ParamArrayAttribute | Показывает, что метод принимает переменное число параметров |
Полезные атрибуты
Неотъемлемой частью разработки программного продукта является отладка. И зачастую в большой и сложной системе требуется десятки и сотни раз запускать один и тот же метод и наблюдать за состоянием объектов. При этом на раз 20 уже начинает конкретно бесить необходимость разворачивать один объект вглубь раз 400, чтоб увидеть значение одной переменной и перезапустить метод заново.
Для более спокойной и быстрой отладки можно использовать атрибуты, модифицирующие поведение отладчика.
DebuggerDisplayAttribute указывает, как отображается тип или его член в окне переменных отладчика (ну и не только).
Единственным аргументом конструктора является строка с форматом отображения. То, что будет находиться между фигурными скобками, будет вычислено. Формат как у интерполированной строки, только без доллара. Нельзя использовать указатели в вычисляемом значении. Кстати, если у вас есть переопределенный ToString, то его значение будет показываться как если бы оно было в этом атрибуте. Если есть и ToString и атрибут, то значение берется из атрибута.
DebuggerBrowsableAttribute определяет способ отображения поля или свойства в окне переменных отладчика. Принимает DebuggerBrowsableState, который имеет 3 опции:
DebuggerTypeProxy — если объект просматривается в отладчике сотни раз в день, то можно заморочиться и потратить минуты 3 на создание прокси объекта, который отобразит исходный объект как надо. Обычно прокси объект для отображения — внутренний класс. Собственно, он и будет отображаться вместо целевого объекта.
Другие полезные атрибуты
ThreadStatic — атрибут позволяющий сделать статическую переменную своей для каждого потока. Для этого надо поставить атрибут над статическим полем. Стоит помнить важный нюанс — инициализация статическим конструктором будет выполнена только один раз, и переменная поменяется в том потоке, который выполнит статический конструктор. В остальных она останется дефолтной. (ЗЫ. Если вам необходимо такое поведение, советую взглянуть в сторону класса ThreadLocal).
InternalsVisibleTo — позволяет указать сборку, которой будут видны элементы, помеченные internal. Может показаться, что если какой-то сборке нужны определенные типы и их члены, можно просто пометить их public и не париться. Но хорошая архитектура подразумевает сокрытие деталей имплементации. Тем не менее они могут понадобиться для каких-нибудь инфраструктурных вещей, например, тестовых проектов. С помощью этого атрибута можно поддерживать и инкапсуляцию, и требуемый процент покрытия тестами.
HandleProcessCorruptedStateExceptions — позволяет отпугивать робких программистов и ловить исключения поврежденного состояния. По умолчанию для таких исключений CLR не выполняет отловки. В общем случае лучшим выходом будет как раз позволить приложению упасть. Это опасные исключения, показывающие, что память процесса повреждена, так что использование данного атрибута — идея очень плохая. Но возможно в некоторых случаях, для локальной разработки будет полезно на некоторое время поставить данный атрибут. Чтобы словить исключение поврежденного состояния, достаточно просто поставить этот атрибут над методом. И если уже дошло до использования этого атрибута, то рекомендуется (впрочем, как и всегда) отлавливать какое-то конкретное исключение.
DisablePrivateReflection — делает все приватные члены сборки недосягаемыми для рефлексии. Атрибут ставиться на сборку.
Определение своего атрибута
Не просто так этом раздел стоит последним. Ведь лучший способ понять, в каких случаях будет выгодно использовать атрибут — посмотреть на уже используемые. Сложно сказать формализованное правило, когда следует задуматься о собственном атрибуте. Зачастую их используют как дополнительную информацию о типе/его члене или другой конструкции языка, которая бывает общей у совершенно разных сущностей. Как пример — все атрибуты, используемые для сериализации/ОРМ/форматирования и тд. Из-за обширного применения данных механизмов к совершенно разным типам, зачастую не известным разработчикам соответствующего механизма, использование атрибутов — отличный способ дать пользователю возможность предоставлять декларативную информацию для данного механизма.
Использование своих атрибутов можно разделить на 2 части:
Создание атрибута и его использование
Для создания своего атрибута достаточно наследоваться от System.Attribute. При этом желательно придерживаться упомянутого стиля именования — заканчивать имя класса на Attribute. При этом никакой ошибки не будет, если опустить этот суффикс. Как упоминалось ранее, атрибуты могут иметь 2 типа параметров — позиционные и именованные. Логика их применения такая же, как и со свойствами и параметрами конструктора у класса — значения, необходимые для создания объекта, для которых не существует разумного «дефолта» выносятся в позиционные (т.е. конструктор). То, чему можно поставить какой-то разумный дефолт, который будет зачастую использован, лучше выделить в именованный (т.е. свойство).
Немаловажным в создании атрибута является ограничение мест его применения. Для этого используется AttributeUsageAttribute. Обязательным параметром (позиционным) является AttributeTarget, определяющий место использования атрибута (метод, сборка и тд). Необязательными (именованными) параметрами являются:
Метод (функция) — тоже информация и тоже может описывать конструкцию. И используя полиморфизм в атрибутах можно предоставить весьма мощный и удобный инструмент, где пользователь сможет влиять как на информацию, используемую вашим инструментом, так и на определенные этапы выполнения и обработки. При этом ему не надо будет плодить классы, внедрять зависимости, стоить фабрики и их интерфейсы, которые будут создавать эти классы. Достаточно будет создать единственный класс-наследник, который инкапсулирует в себе детали работы с элементом, к которому он относится. Но, как правило, достаточно обычного «РОСО» атрибута с парой свойств.
Получение и обработка атрибута
Обработка полученных атрибутов зависит от конкретного случая и может быть сделана абсолютно по-разному. Сложно привести полезные для этого функции и приемы.
Получение атрибутов во время выполнения осуществляется с помощью рефлексии. Для получения атрибута с определенного элемента существуют различные способы.
Но все берет начало от интерфейса ICustomAttributeProvider. Его реализуют такие типы как Assembly, MemberInfo, Module, ParameterInfo. В свою очередь наследниками MemberInfo являются Type, EventInfo, FieldInfo, MethodBase, PropertyInfo.
Интерфейс имеет лишь 3 функции, и они не очень удобные. Они работают с массивами (даже если мы знаем, что атрибут может быть лишь один) и не параметризованы типом (используют object). Поэтому напрямую к функциям этого интерфейса придется обращаться редко (не сказал никогда, потому что не хочу быть категоричным). Для удобства использования существует класс CustomAttributeExtensions, в котором собрано множество методов расширения для всевозможных типов, выполняющих несложные операции по приведению типов, выборке единственного значения и так далее, тем самым освобождая разработчика от данной необходимости. Также эти методы доступны как статические в классе Attribute с полезнейшей функцией игнорирования параметра inherit (для нонконформистов).
Основные используемые функции приведены ниже. Первый параметр, указывающий какой тип расширяет метод, я опустил. Также везде, где указан параметр bool inherit существует перегрузка без него (со значением по умолчанию true). Этот параметр указывает, нужно ли учитывать при выполнении метода атрибуты родительского класса или базового метода (если используется на переопределенном методе). В случае, если в атрибуте inherit = flase, то даже установка его в true не поможет учитывать атрибуты базового класса
Название метода | Описание |
---|---|
GetCustomAttributes (bool inherit) | получает перечисление атрибутов указанного типа. Если атрибут один, вернется перечисление из 1 элемента |
GetCustomAttribute (bool inherit) | возвращает единственный атрибут указанного типа. Если таких несколько, выбрасывает исключение System.Reflection.AmbiguousMatchException: Multiple custom attributes of the same type found |
GetCustomAttributes() | возвращает перечисление атрибутов всех типов |
GetCustomAttributesData() | возвращает перечисление CustomAttributeData, в котором есть свойства позволяющие получить конструктор, параметры (именованные и позиционные), аргументы конструктора |
IsDefined(Type attrType, bool inherit) | возвращает true, если атрибут объявлен над элементом, false если нет |
Для наглядности предлагаю взглянуть на небольшое демо работы всех упомянутых функций.
Ну и для академического интереса привожу пример определения атрибутов во время выполнения. Данный код не претендует на звание самого красивого и поддерживаемого.