Спадкування форми від свого класу

 public abstract class BasePage: System.UI.WebControls.Page {
public virtual abstract void DoSearchModuleAction (int recordCount);
}
public class MyPage : BasePage {
  public override void DoSearchModuleAction(int recordCount) { 
/ / Тут виконується реальна робота
  }
}
public class SeachModule : System.UI.WebControls.Control {
  private void Button1_Click() {
    if (Page is BasePage) 
      ((BasePage) Page).DoSearchModuleAction(Search());
  }
  private int Search() {
    return 0;
  }
} 

Цей варіант має такі недоліки:

Визначення цільових інтерфейсів

Вище за приклад був наведений код, який ілюструє виклик методу
DoSearchModuleAction сторінки-власника з обробника натискання
кнопки в компоненті SeachModule. Ключова рядок:

    if (Page is BasePage) ...

Оператор is виконує перевірку того, що Page є
екземпляром класу BasePage (Або його спадкоємцем), або – УВАГА
– Що об'єкт Page реалізує інтерфейс BasePage.
Природним чином напрошується рішення використовувати не спадкування,
а реалізацію інтерфейсів:

public interface IBasePage {
  void DoSearchModuleAction(int recordCount);
}
public class MyPage : System.UI.WebControls.Page, IbasePage {
public void IBasePage.DoSearchModuleAction (int recordCount) { 
/ / Тут виконується реальна робота
  }
}
public class SeachModule : System.UI.WebControls.Control {
  private void Button1_Click() {
    if (Page is IBasePage) 
      ((IBasePage) Page).DoSearchModuleAction(Search());
  }
  private int Search() {
    return 0;
  }
} 

Цей варіант візуально не дуже відрізняється від варіанту спадкування,
але за рахунок використання інтерфейсів досягається головна мета – з одного
боку, компонент не зобов'язаний орієнтуватися на конкретну форму, а
може бути встановлений в будь-якій контейнер, будь то форма або інший
компонент, і, з іншого боку, забезпечує досить простий спосіб
взаємодії з формою-власником.

Тим не менше, і в цьому варіанті можна знайти деякі недоліки:

Використання делегатів

Передати управління формі-власнику можна наступним чином:

public delegate void SearchModuleDelegate(int recordCount);
public class MyPage : System.UI.WebControls.Page {
  protected SeachModule SeachModule1;
  public void PageLoad() {
/ / Підключення делегата до компоненту
SeachModule1.Action = new SearchModuleDelegate (DoSearchModuleAction);
  }
  private void DoSearchModuleAction(int recordCount) {
/ / Тут виконується реальна робота
  }
}
public class SeachModule : System.UI.WebControls.Control {
  public SearchModuleDelegate Action = null;
  private void Button1_Click() {
    if (Action != null) Action(Search()); 
  }
  private int Search() {
    return 0;
  }
} 

Деякі пояснення:

Цікава можливість, притаманна делегатам, – підключати кілька
делегатів:

delegate void D(int x);
class C {
  public static void M1(int i) { /* ... */ }
  public static void M2(int i) { /* ... */ }
}
class Test {
  static void Main() { 
    D cd1 = new D(C.M1);  // M1
    D cd2 = new D(C.M2);  // M2
    D cd3 = cd1 + cd2;    // M1 + M2
    D cd4 = cd3 + cd1;    // M1 + M2 + M1
    D cd5 = cd4 + cd3;    // M1 + M2 + M1 + M1 + M2
  }
}

Примітка: Приклад взято з розділу 15.1 специфікації мови C #.

 

Генерація подій

Використання подій мало чим відрізняється від розглянутого вище
варіанту, тому що обробники подій представляють собою не що інше, як
стандартизовані (по типу значення, що повертається і набору параметрів)
делегати:

public delegate void SearchEventHandler (object sender, SearchEventArgs e);
public class SearchEventArgs : System.EventArgs {
  public readonly int RecordCount;
  public SearchEventArgs(int recordCount) : base() {
    RecordCount = recordCount;
  }
}
public class MyPage : System.UI.WebControls.Page {
  protected SeachModule SeachModule1;
  public void PageLoad() {
/ / Підключення обробника події до компоненту
SeachModule1.Action + = new SearchEventHandler (DoSearchModuleAction);
  }
private void DoSearchModuleAction (object sender, SearchEventArgs e) {
/ / Тут виконується реальна робота
  }
}
public class SeachModule : System.UI.WebControls.Control {
  public event SearchEventHandler Action;
  private void Button1_Click() {
if (Action! = null) Action (this, new SearchEventArgs (Search ())); 
  }
  private int Search() {
    return 0;
  }
} 

Відмінності від використання делегатів:

Як недолік, – при використанні стандартної схеми обробки подій
може виникати необхідність у написанні спеціалізованих
класів-спадкоємців від System.EventArgs. Втім, написання
спеціалізованих аргументів події можна уникнути, якщо використовувати,
наприклад, властивості компонента (нижче наводиться модифікований приклад
обробника події):

public class MyPage : System.UI.WebControls.Page {
  protected SeachModule SeachModule1;
  public void PageLoad() {
/ / Підключення обробника події до компоненту
SeachModule1.Action + = new EventHandler (DoSearchModuleAction);
  }
private void DoSearchModuleAction (object sender, EventArgs e) {
    int recordCount = (sender is SeachModule)
 ? ((SeachModule) sender).RecordCount : -1;
    // TODO: add code to interpret recordCount
  }
}
public class SeachModule : System.UI.WebControls.Control {
  public event EventHandler Action;
  private int recordCount = -1;
  private void Button1_Click() {
    if (Action != null) {
      recordCount = Search(); 
      Action(this, null);
    }
  }
  private int Search() {
    // TODO: add code to search person
    return 0;
  }
  public int RecordCount {
    get {
      return recordCount;
    }
  }
} 

Висновки

Обробники подій є "стандартом де-факто", тому їх
використання у більшості випадків має бути зрозуміло будь-якому
сторонньому розробнику, що є очевидною перевагою з точки
зору супроводу або відчуження вихідного тексту.

У деяких випадках, наприклад, якщо програмний продукт
розробляється не для відчуження і внутрішні стандарти компанії
передбачають відповідні рішення, можна використовувати більш
прості схеми: делегати та / або інтерфейси.

Використання механізму наслідування для реалізації взаємодії
компонентів і форм не рекомендується.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*