Но через какую-то неделю (не без моего настойчивого требования) было принято решение переходить на .NET 3.5. И тут началось раздолье! Однако, сложилось такое ощущение, что только меня это и радовало. Все, как писали на 2.0, так и писали...
История
Параллельно читая знаменитый всему айтишному миру Habr, наткнулся на статью Дмитрия про реализацию "Монадического синтаксиса" из фукнционального программирования на методах-раширениях. Стало очень интересно про сии цепочные методы. Прочитал всю статью взахлеб! Взял на вооружение все методы, но чаще всего пользуюсь только четырьмя. Хочу ими с вами поделиться (комментарии кода были опущены).
public static TInput If<TInput>(this TInput source, Func<TInput, bool> evaluator) where TInput : class { if (source == null) { return null; } return evaluator(source) ? source : null; }
public static TInput Do<TInput>(this TInput source, Action<TInput> action) where TInput : class { if (source == null) { return null; } action(source); return source; }
public static TResult With<TInput, TResult>(this TInput source, Func<TInput, TResult> evaluator) where TInput : class where TResult : class { return source == null ? null : evaluator(source); }
public static TResult Return<TInput, TResult>(this TInput source, Func<TInput, TResult> evaluator, TResult defaultValue) where TInput : class { return source == null ? defaultValue : evaluator(source); }
Сиквел ака "А теперь как сие счастье можно использовать?"
- Самый простой пример: предположим, что у вас в переменной хранится путь к файлу, но неизвестно, существует ли он. Используя методы, указанные выше, можно написать следующим образом:
file.If(File.Exists).Do(File.Delete);
- Далее данные методы можно использовать при формировании sql-запроса: предположим, что у вас есть много полей, которые отвечают за определенные поля в базе данных. Например, таблица пользователей (упрощенный вариант) состоит из 3 полей (ID, NAME, AGE). На форме у вас существует 3 поля: подстрока имени и две границы возраста. Теперь напишем формирование запроса, используя наши методы-расширения:
StringBuilder query = new StringBuilder("select * from USERS where 1=1"); this.txtName.With(box => box.Text) .If(name => !string.IsNullOrEmpty(name)) .Do(name => query.AppendFormat(" and NAME like '%{0}%'", name)); this.txtMinAge.With(box => box.Text) .If(minAge => !string.IsNullOrEmpty(minAge)) .Do(minAge => query.AppendFormat(" and AGE >= {0}", minAge)); this.txtMaxAge.With(box => box.Text) .If(maxAge=> !string.IsNullOrEmpty(maxAge)) .Do(maxAge=> query.AppendFormat(" and AGE <= {0}", maxAge)); query.Append(" order by AGE desc");
- Также можно определять уровень доступа текущего пользователя (его роль). Если он анонимный, то выдавать ему минимальный уровень. Например так:
return this.User.Return(user => user.AccessLevel, "0");
или
return this.User.Return(user => user.Role, Roles.Anonymous);
- Я использую эти методы для вызова событий, так как данные методы содержат внутренню проверку на null:
this.OnRequestConfirmed.Do(ev => ev());
И ещё много вариантов использования данных методов. Надеюсь, что вам они тоже придутся по вкусу, потому что на работе не с кем поделиться этими знаниями, потому что никто не хочет... =\
P.S. Ссылка на оригинальную статью: Паттерны методов расширения
Комментариев нет:
Отправить комментарий