Всем привет! Помните, когда-то давным давно была хорошая серия статей? Так вот я хочу ее продолжить. Однако на этот раз я не буду рассматривать огромное множество библиотек, которые решают повсеместно-возникающие проблемы, а рассмотрю всего лишь одну, но способную решить огромную кипу проблем. Мне кажется каждый из вас когда-то писал строчки вида:
Кто-то пытался превратить это в:
Кто-то превращал это во что-то похожее. Однако у всех, я могу поспорить, оставался осадок что что-то тут не так. Красивее было бы как-то по другому. А что в итоге? Огромное количество велосипедов с квадратными колесами! Как сделать по-другому?
Так вот по-другому, когда душа радуется и код чистый, это когда пишешь так:
Согласитесь, приятно! Вы можете мне возразить, сказав что атрибуты – это все равно что теги к статье: пока их никто не прочитает, магия не сработает. И вы будете правы. Та программа, о которой я хочу рассказать – PostSharp, позволяет делать такие вещи. Вы пишите атрибут, который будет прикладываться к параметрам метода и который будет вставлять в код программы проверку на null. Если null, то генерируем exception. С этого момента вам не надо засорять каждый метод мусором. Теперь достаточно лишь пометить необходимые методы необходимыми атрибутами:
Теперь поговорим о другой проблеме, которая обсуждалась уже много раз, но люди упорно делают свои логгеры, свои трейсеры и прочие радости велосипедостроения (кстати, а вы знаете что недавно сделали велосипед с “автоматом”?). Хорошо что сделали такие вещи как log4net, например. Однако это не всегда работает так быстро как хочется. С нашей программой внедрение логгирования будет работать максимально быстро, а само логгирование будет работать со скоростью самописного кода:
В этом примере некий скряга хочет чтобы каждое действие с его денежными средствами записывалось бы в базу данных, при этом проверялась бы история операций и обругивались все кто пытается на эти деньги что-то купить. Пример, конечно, выдуманный и эти атрибуты (кроме трассировки) вам вряд ли понадобятся, однако они ясно показывают возможности происходящего. Тут вам и работа с базой и трассировка и проверка значений на диапазоны. Вы можете возразить: вот буду я городить непонятное облако атрибутов, загромождать пространство! Однако, попробую спарировать: разве проще выглядит такой код?
Совсем нет, но решать вам :) Существует также большое количество вариантов, когда это работает отлично! Когда это работает на 10 баллов из 5. Например, трассировка сообщений на ASP.NET в консоль разработчика в то время как веб-сайт уже работает… Вы можете посмотреть историю стек-трейса на любой момент работы веб-странички. Как? Просто напишите аспект, который будет сохранять стек куда-нибудь и наложите на сборку. Или какие-то еще на первый взгляд, странные вещи. Я расскажу о них чуть позже… А пока просто приведу ряд ссылок на статьи, в которых я уже рассказывал о фичах, реализуемых этой программой:
void SomeMethod(IEmployee lazyguy) { if(lazyguy == null) throw new ArgumentException(“lazyguy”); // Do something with lazy guy. Fire him, for example. }
Кто-то пытался превратить это в:
void SomeMethod(IEmployee lazyguy) { UniversalValidator.CheckNotNull(lazyguy); // Meet with him and talk about motivations }
Кто-то превращал это во что-то похожее. Однако у всех, я могу поспорить, оставался осадок что что-то тут не так. Красивее было бы как-то по другому. А что в итоге? Огромное количество велосипедов с квадратными колесами! Как сделать по-другому?
Так вот по-другому, когда душа радуется и код чистый, это когда пишешь так:void SomeMethod([NotNull] IEmployee lazyguy) { // Promote him to be head of department }
Согласитесь, приятно! Вы можете мне возразить, сказав что атрибуты – это все равно что теги к статье: пока их никто не прочитает, магия не сработает. И вы будете правы. Та программа, о которой я хочу рассказать – PostSharp, позволяет делать такие вещи. Вы пишите атрибут, который будет прикладываться к параметрам метода и который будет вставлять в код программы проверку на null. Если null, то генерируем exception. С этого момента вам не надо засорять каждый метод мусором. Теперь достаточно лишь пометить необходимые методы необходимыми атрибутами:
public class LazyEmployee : IEmployee { string Name { get; } string LastName { get; } [GreaterThan(VeryCleverGuySalary)] int Salary { get; set; } [Only(true)] bool NeedsPersonalSecretary { get; set; } [TypeOf(typeof(IRoomWithSaunaAndPersonalPlayStation))] IRoom Room { get; set; } }
Теперь поговорим о другой проблеме, которая обсуждалась уже много раз, но люди упорно делают свои логгеры, свои трейсеры и прочие радости велосипедостроения (кстати, а вы знаете что недавно сделали велосипед с “автоматом”?). Хорошо что сделали такие вещи как log4net, например. Однако это не всегда работает так быстро как хочется. С нашей программой внедрение логгирования будет работать максимально быстро, а само логгирование будет работать со скоростью самописного кода:
public class PerisherEmployee : IEmployee { [NotNull, StartingWithUpperCase] string Name { get; } [NotNull, StartingWithUpperCase] string Lastname { get; } [Tracing, WriteToDatabaseEachTransaction, CheckHistory] int Salary{ get; set; } [AbuseEachWhoTriesToBuySomething, Trace] int FreeMoney { get; set; } }
В этом примере некий скряга хочет чтобы каждое действие с его денежными средствами записывалось бы в базу данных, при этом проверялась бы история операций и обругивались все кто пытается на эти деньги что-то купить. Пример, конечно, выдуманный и эти атрибуты (кроме трассировки) вам вряд ли понадобятся, однако они ясно показывают возможности происходящего. Тут вам и работа с базой и трассировка и проверка значений на диапазоны. Вы можете возразить: вот буду я городить непонятное облако атрибутов, загромождать пространство! Однако, попробую спарировать: разве проще выглядит такой код?
public class PerisherEmployee : IEmployee { string _name, _lastname; int _salary, _freemoney; string Name { set { if(value == null) throw new ArgumentNullException("value"); if(!IsStartsFromUpperCase(value)) throw new ArgumentOutOfRangeException("value"); _name = value; } get { return _name; } } string Lastname { set { if(value == null) throw new ArgumentNullException("value"); if(!IsStartsFromUpperCase(value)) throw new ArgumentOutOfRangeException("value"); _surname = value; } get { return _surname; } } [Tracing, WriteToDatabaseEachTransaction, CheckHistory] int Salary { get { return _salary; } set { Console.WriteLine("value: {0}", value); DatabaseEngine.SaveSalary(value); _salary = value; if(!CheckHistory(this)) throw new WrongOperationException(); } } int FreeMoney { get { return _freememory; } set { if(value < _freememory) throw new OutOfRangeException(); Console.WriteLine("value: {0}", value); } } }
Совсем нет, но решать вам :) Существует также большое количество вариантов, когда это работает отлично! Когда это работает на 10 баллов из 5. Например, трассировка сообщений на ASP.NET в консоль разработчика в то время как веб-сайт уже работает… Вы можете посмотреть историю стек-трейса на любой момент работы веб-странички. Как? Просто напишите аспект, который будет сохранять стек куда-нибудь и наложите на сборку. Или какие-то еще на первый взгляд, странные вещи. Я расскажу о них чуть позже… А пока просто приведу ряд ссылок на статьи, в которых я уже рассказывал о фичах, реализуемых этой программой:
- Официальный сайт PostSharp с огромной библиотекой статей и богатой документацией
- Отложенная загрузка зависимостей
- Менеджмент транзакций
- Логгирование и аудит
- Автоматическое кэширование