Реальное использование пользовательских атрибутов .NET
-
06-07-2019 - |
Вопрос
Для каких целей вы использовали пользовательские атрибуты .NET в реальном мире?
Я читал о них несколько статей, но никогда не использовал пользовательские атрибуты.
Мне кажется, что я упускаю из виду их, хотя они могут быть полезны.
Я говорю об атрибутах, которые вы создаете, а не о тех, которые уже включены в структуру.
Решение
Я использовал их " custom " атрибуты для проверки (т. е. пометка поля, подлежащего проверке, с помощью моей собственной «проверки кредитной карты») и пользовательских анализаторов LinqToLucene, которые я написал (т. е. указание, какой анализатор использовать в данном поле).
Код проверки, например, будет выглядеть примерно так:
public class Customer
{
[CreditCardValidator]
string creditCardNumber;
[AddressValidator]
string addressLineOne
}
Когда объект, указанный выше, проверен, каждое поле проверяется соответствующим валидатором благодаря функции " custom " атрибут.
В материалах LinqToLucene, которые я написал, пользовательские атрибуты хороши тем, что позволяют находить (через отражение) определенные поля во время выполнения. Например, если у вас есть объект customer, вас может заинтересовать получение всех свойств, помеченных как " index me " ;: настраиваемый атрибут позволяет вам легко это сделать, поскольку он предоставляет метаданные об объекте способом это легко запросить.
Другие советы
Я создал механизм сценариев и пометил различные методы атрибутом [Command].Это означало, что эти функции были доступны скриптовому движку.
Пример:
[Command(HelpText = "Lists active users")]
void ListUsers(void)
{
}
[Command(HelpText = "Terminate a specific user's connection")]
void EndConnection(int userID)
{
}
И как используется:
MyScriptEngine>> Help
Available Commands are:
ListUsers: Lists active users
EndConnection {userID}: Terminate a specific user's connection
MyScriptEngine>> EndConnection 3
User 3 (Michael) has had his connection terminated.
MyScriptEngine>>
Помимо прочего, я использовал их для указания EBNF, который считывается во время выполнения, для создания пользовательских парсеров «на лету», а также для указания метаданных о полях базы данных.
Я нахожу один «шаблон», который я обычно использую настраиваемые атрибуты, — это замена перечислений, особенно когда существует зависимость от перечисления в различных местах кода.
Например.У меня могло бы быть перечисление для состояния объекта.В зависимости от этого состояния у меня есть, возможно, 3 или 4 разных места в коде, в которых я бы «переключил» это перечисление и выполнил некоторую операцию.Какой-нибудь другой разработчик мог бы легко допустить ошибку, добавив новое перечисление, но не обработав его в одном из операторов переключения где-то еще в коде.
Поэтому, чтобы избежать этого, я создаю собственные атрибуты, объявленные для статического класса.Пользовательские атрибуты загружаются в статическом конструкторе класса в словарь, и во всех местах кода вместо операторов переключения используется словарь.Конструктор настраиваемых атрибутов содержит «жестко закодированные» значения для каждого оператора переключения.
Мне пришлось сериализовать некоторые объекты в пользовательский (устаревший) формат, и я использовал атрибуты, чтобы определить, какие поля следует сериализовать и как их форматировать. Затем у меня был сериализатор, который мог взять любой объект с этими атрибутами и использовать отражение для его форматирования.
Я пока не нашел использования пользовательских атрибутов. Было несколько ситуаций, когда я думал, что они могут быть подходящими, но не использовал их, потому что, очевидно, отражение при чтении пользовательских атрибутов довольно дорого.
Я поместил пользовательские атрибуты в классы внутри " плагина " Библиотеки DLL. Это позволяет платформе динамически обнаруживать доступные плагины, оценивать, представляют ли они интерес, а затем динамически загружать те, которые представляют интерес.
В нашем домене, например, плагины, которые моделируют определенные транспортные средства в семье. Один плагин для семейства транспортных средств может фактически моделировать несколько моделей транспортных средств в пределах семейства транспортных средств (например, «MX-6», «Probe»). Если идентификатор или имя модели включены в качестве массива настраиваемых атрибутов, мы можем быстро игнорировать любые библиотеки DLL, которые даже не имеют настраиваемых атрибутов, а затем дополнительно игнорировать любые библиотеки, которые не моделируют интересующий вас транспорт.
Я использовал его в одной из структур ORM, которую я разработал на основе шаблона ActiveRecord. Это та же самая реализация, которая доступна в LINQ, проекте Castle и т. Д.
Фреймворк назывался «SkyFramework», но не был открытым исходным кодом.
<р> например Просто грубый пример ...Подобные примеры вы найдете и в других проектах с открытым исходным кодом.
<код> код>
<код>[Sky.Table ("user")]
public class User
{
[Sky.Column ("username")]
public string UserName;
[Sky.Column ("pwd")]
public string Password;
}
Код> <код> код>
ПРИМЕЧАНИЕ. Атрибут «Таблица», «Столбцы» были пользовательские атрибуты в то время.
Механизм ActiveRecord анализирует объект на предмет этих атрибутов и генерирует соответствующие функции для CRUD ... и т. д.
Точно так же я разработал некоторые пользовательские атрибуты для определения частей кода, которые необходимо сравнить ... например,
.[Sky.BenchMark()]
public void LongRunningMethod(..)
{
}
Методы, отмеченные вышеуказанными атрибутами, автоматически помечаются, и создается журнал. Это были некоторые более ранние реализации.
По этой теме доступна книга Apress. Прикладные атрибуты .NET , которые могут вам помочь. р>