Всем привет! Помните, когда-то давным давно была хорошая серия статей? Так вот я хочу ее продолжить. Однако на этот раз я не буду рассматривать огромное множество библиотек, которые решают повсеместно-возникающие проблемы, а рассмотрю всего лишь одну, но способную решить огромную кипу проблем. Мне кажется каждый из вас когда-то писал строчки вида:
Кто-то пытался превратить это в:
Кто-то превращал это во что-то похожее. Однако у всех, я могу поспорить, оставался осадок что что-то тут не так. Красивее было бы как-то по другому. А что в итоге? Огромное количество велосипедов с квадратными колесами! Как сделать по-другому?
Так вот по-другому, когда душа радуется и код чистый, это когда пишешь так:
Согласитесь, приятно! Вы можете мне возразить, сказав что атрибуты – это все равно что теги к статье: пока их никто не прочитает, магия не сработает. И вы будете правы. Та программа, о которой я хочу рассказать – 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 с огромной библиотекой статей и богатой документацией
- Отложенная загрузка зависимостей
- Менеджмент транзакций
- Логгирование и аудит
- Автоматическое кэширование