Естесственно, чтобы не нарушить защиту класса, методам расширения недоступны “кишки” класса, к которому они пристраиваются. Метод расширение обязан пользоваться существующим публичным контрактом.
Фактически, это такой способ подстроить синтаксис уже существующей библиотеки/фреймворка “под себя”, уменьшив количество кода, которое нужно написать для реализации требуемой функциональности (любители Nemerle меня поймут :-)
Передо мной недавно встала следующая задача: во множестве пользовательских контролов ASP.NET приложения нужно было анализировать дерево контролов страницы и выцепить из него самый первый контрол, который реализовал определенный интерфейс.
Метод FindControl для этого не подходил – я не имел возможности задавать имя контрола. В результате были написаны пара методов-раширений, которые добавляли требуемую функциональность
/// <summary>Метод AllControls() возвращает коллекцию всех элементов в дереве Page Controls (конструкция yield return позволяет не строить вручную коллекцию через ListArray)
/// returns all controls by wisiting control hierarchy
/// </summary>
public static IEnumerable<Control> AllControls(this Control control)
{
foreach (Control c in control.Controls)
{
yield return c; // build up control collection implicitly
if (c.Controls.Count > 0)
{
foreach (Control cc in AllControls(c))
yield return cc; // build up control collection implicitly
}
}
}
/// <summary>
/// returns all controls on page implementing a given interface
/// </summary>
public static T FirstControlOfType<T>(this Control control) where T : class
{
foreach (var cn in control.AllControls())
{
var c = cn as T;
if (c != null)
return c;
}
return null;
}
Метод FirstControlOfType() возвращает первый встретившийся в дереве контрол, реализующий требуемый интерфейс
Пользоваться расширениями – одно удовольствие:
private DateTime DateFilterЧем методы расширения лучше статических методов? Тем, что во-первых не нужно помнить имена всевозможных ControlUtils, DateUtils, StringUtils, а во-вторых, при кодировании ты концентрируешься своей задаче, а не на хелперах, которые помогают задачу решать.
{
get
{
var filtered = this.Page.FirstControlOfType<IFilteredByDate>();
return filtered == null ? DateTime.Now: filtered.DateFilter;
}
}
То есть “пляшешь” от реальных данных, не размазываешь свое внимания по финтифлюшечкам.
3 комментария:
Приятно, что .NET потихоньку движется в сторону нормальных языков программирования, типа Python :-D
Да скорее питон движется к .net, вот только как-то медленно
а в питоне есть свой аналог extension methods?
Отправить комментарий