2013-05-21 2 views
0

Можно ли отправить ссылку «sender» без указания его явно как параметра в обработке событий на основе делегатов?Отказать отправителю делегатов

У меня есть внутренний класс, который вызывает некоторые события, и я хочу явно вызывать события для целей тестирования.

public class Manager { 
    public class DataStruct { 
     public int Id { get; private set; } 
     public event EventHandler Event1; // Can't be called by other classes 
     public void fireEvent1(Event1();} // So another caller... 

     // Delegates *can* be called by other classes 
     public delegate void DelegateHandler(DataStruct sender); 
     public DelegateHandler NewEvent; 

     public void DelegateHandler(DataStruct sender) { 
      MessageBox.Show(string.Format(
       "{0} raises event", sender.Id)); 
     } 
    } 
} 

// Form1 /////////////////////////////////////////////////////////////////// 
partial class Form1 { 
    Manager.DataStruct dsRaiser, dsListener; 

    private void Form1_Load(object sender, EventArgs e) { 
     dsRaiser.Event1 += dsListener.SOME_HANDLER; 
     dsRaiser.NewEvent += dsListener.DelegateHandler; 
    } 
    private void button1_Click(object sender, ...) { 
     dsRaiser.fireEvent1(); // No argument needed but fireEvent1, not Event1(). 
    } 
    private void button2_Click(object sender, ...) { 
     dsRaiser.NewEvent(dsRaiser); // Way to omit parameter dsRaiser? 
    }   
////////////////////////////////////////////////////////////////////////// 
+0

Можете вы пометить 'Event1' как внутреннюю? –

+0

Возможно, мне не хватает точки модульного тестирования, но разве вы не должны тестировать условия/триггеры, которые заставляют «DataStruct» (что смутно является «классом»?) Поднимать само событие, а не _forcing_ событие стрелять? Что это должно быть тестирование? –

ответ

1

Если вашему методу обработчика необходимо использовать ссылку отправителя, вам необходимо передать эту ссылку. Если нет, просто объявите делегат без прав без ограничений, например Action.

Но при рассмотрении событий этот параметр должен передаваться классом, который вызывает само событие. (Помните, что события не предназначены для вызова извне).

Итак, если вы действительно хотите использовать простой делегат вместо события, вам придется передать параметры. Если вам нужен отправитель, вам нужно будет сделать именно то, что вы сделали с событием: создайте метод, чтобы «поднять» делегата, и в этом методе вы передаете this в качестве отправителя.

Но, учитывая, что вы должны делать то же самое в обоих случаях, я бы наверняка использовал это событие.

public class DataStruct { 
    public int Id { get; private set; } 
    public event EventHandler Event1; // Can't be called by other classes 

    // you need to pass those parameters to the event when called. 
    public void fireEvent1{Event1(this, new EventArgs());} 

    // Delegates *can* be called by other classes, but only with all parameters passed. 
    public delegate void DelegateHandler(DataStruct sender); 
    public DelegateHandler NewEvent; 

    // To avoid passing parameters, you need to do exactly what you did with the event 
    public void RaiseDelegate() { NewEvent(this); } 

    public void DelegateHandler(DataStruct sender) { 
     MessageBox.Show(string.Format(
      "{0} raises event", sender.Id)); 
    } 
}