2010-07-22 2 views
3

У меня есть объект, который является приватным в моем классе. Если этот объект запускает событие, я хочу передать событие на все, что используется моим классом. В настоящее время я делаю это так, я положил в мой конструктор:Событие, запускающее событие

cbName.CheckedChanged += ((sender, args) => this.CheckChanged(this,args)); 

Есть ли лучший способ сделать это, и есть ли подводные камни, как класс обыкновение быть утилизированы, поскольку он имеет событие само по себе, и я буду нужно вручную отказаться от подписки в функции удаления?

Изменение отправителя от объекта обжига до this не является обязательным.

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

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace placeholder 
{ 
    internal class FilterBase : UserControl, IFilterObject 
    { 
     public FilterBase(string name) 
     { 
      InitializeComponent(); 
      cbName.CheckedChanged += ((sender, args) => this.CheckChanged(this,args)); 
      cbName.Name = name; 
      this.Name = name; 
     } 

     private CheckBox cbName; 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     private System.ComponentModel.IContainer components = null; 

     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> 
     protected override void Dispose(bool disposing) 
     { 
      if (disposing && (components != null)) 
      { 
       components.Dispose(); 
      } 
      base.Dispose(disposing); 
     } 

     #region Component Designer generated code 

     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     private void InitializeComponent() 
     { 
      this.cbName = new System.Windows.Forms.CheckBox(); 
      this.SuspendLayout(); 
      // 
      // cbName 
      // 
      this.cbName.AutoSize = true; 
      this.cbName.Location = new System.Drawing.Point(4, 4); 
      this.cbName.Name = "cbName"; 
      this.cbName.Size = new System.Drawing.Size(79, 17); 
      this.cbName.TabIndex = 0; 
      this.cbName.Text = "Filter Name"; 
      this.cbName.UseVisualStyleBackColor = true; 
      // 
      // UserControl1 
      // 
      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 
      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 
      this.AutoSize = true; 
      this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 
      this.Controls.Add(this.cbName); 
      this.Name = "Filter Name"; 
      this.Size = new System.Drawing.Size(86, 24); 
      this.ResumeLayout(false); 
      this.PerformLayout(); 

     } 

     #endregion 

     public event EventHandler CheckChanged; 
     public bool Checked 
     { 
      get { return cbName.Checked; } 
     } 
    } 
} 

ответ

3

event на самом деле схож с авто-недвижимостью. Вы можете определить свою собственную add и remove методы, которые проходят делегат непосредственно на дочернем элемент управления, следовательно, удаление дополнительного уровня косвенности:

public event EventHandler CheckChanged { 
    add { cbName.CheckChanged += value; } 
    remove { cbName.CheckChanged -= value; } 
} 

Это удалит дополнительный Delegate хранятся в вашем классе (как Delegate поля используется за кадром стандартного события)

+0

Прохладный, не знал об этом. –

+0

Есть ли способ получить мой торт и съесть его тоже с изменением отправителя cbName на FilterBase, используя что-то вроде этого? –

+0

Как всегда, у Джона Скита есть отличная статья о работе здесь: http://csharpindepth.com/Articles/Chapter2/Events.aspx. Обязательно возьмите гангер о безопасности потоков, если это относится к вашей ситуации. –

1

Ну, что предотвратит текущий объект из собираемых мусора, а cbName жив, но это звучит, как это вряд ли будет проблемой ... и это присуще тот факт, что у вас есть ссылка на , что бы вы ни делали (потому что вы хотите запустить обработчиков CheckChanged этого объекта).

С одной стороны, вы не можете отказаться от подписки (например, в методе Dispose), даже если хотите. В качестве альтернативы можно использовать фактический метод:

private void CbNameCheckedChangedHandler(object sender, EventArgs e) 
{ 
    CheckedChanged(this, args); 
} 

... 
cbName.CheckedChanged += CbNameCheckedChangedHandler; 

// If you ever want to remove the handler 
cbName.CheckedChanged -= CbNameCheckedChangedHandler; 

Заметьте, что все это при условии, что ваш CheckedChanged событие является нуль-сейф, например, что он объявлен как:

public event EventHandler CheckedChanged = delegate {}; 

В противном случае, если никто не подписался на событие, вы получите NullReferenceExceptioncbName.CheckedChanged, когда пожары.

+0

Спасибо за предупреждение Null Reference! –

Смежные вопросы