2011-09-09 79 views
0

我有一些需要重構的代碼有問題。現在它使用lambda作爲事件處理程序,但它們不能正確刪除。從我讀過的內容來看,這甚至不可能?無論如何,我想重寫它使用委託,而不是一個匿名函數,現在我的問題是,現在它需要一個行動作爲參數,我似乎無法弄清楚如何將行動傳遞給我的新代表。這是代碼:向事件處理程序參數添加一個動作c#

void RetrieveData(
      int pointId, 
      int? chartCollectionId, 
      Action action) 
     { 
      if (pointId <= 0) 
       throw new ArgumentException("PointId not valid"); 

      LastPointId = NextPointId; 
      NextPointId = pointId; 

      Clear(); 

      _csr = new CustomerServiceRepository(); 

      _csr.ServiceClient.GetChartDataCompleted += (se, ea) => 
                  { 
                   _cachedCharts = ea.Result; 
                   ChartDataRetrieved(ea.Result); 
                   if (action != null) 
                    action.Invoke(); 
                   _csr = null; 
                  }; 
      _csr.ServiceClient.GetChartDataAsync(
       Settings.Current.Customer.CustomerName, 
       pointId, 
       chartCollectionId); 

      _csr.ServiceClient.GetChartDataCompleted -= (se, ea) => //remove after usage 
                  { 
                   _cachedCharts = ea.Result; 
                   ChartDataRetrieved(ea.Result); 
                   if (action != null) 
                    action.Invoke(); 
                   _csr = null; 
                  }; 
     } 

我在想,也許我可以創建以下文件:

public class extendedEventArgs : GetChartDataCompletedEventArgs 
     { 
      Action foo { get; set; } 
     } 

     void tang(object sender, extendedEventArgs e) 
     { 
      _cachedCharts = e.Result; 
      ChartDataRetrieved(e.Result); 
      if (action != null) 
       action.Invoke(); 
      _csr = null; 
     } 

而且通過行動在擴展事件參數的參數,但是當我嘗試使用像這樣

_csr.ServiceClient.GetChartDataCompleted += new EventHandler<extendedEventHandler>(tang); 

它給出了一個錯誤:

Cannot implicitly convert type System.EventHandler<Conwx.Net.Client.CustomerClient.Controls.ChartControls.ChartListForecast.extendedEventArgs>' to System.EventHandler<Conwx.Net.Client.Framework.CustomerServiceReference.GetChartDataCompletedEventArgs>' 

我在這裏做錯了什麼?替代解決方案也受到歡迎。

.K

回答

1

當我讀到它時,這裏的關鍵問題是無法刪除處理程序;如果是這樣,你需要它來存儲委託(其中在下面,YourDelegateType意在表示:該定義類型的GetChartDataCompleted):

YourDelegateType handler = (se, ea) => 
    { 
     _cachedCharts = ea.Result; 
     ChartDataRetrieved(ea.Result); 
     if (action != null) 
      action.Invoke(); 
     _csr = null; 
    }; 
_csr.ServiceClient.GetChartDataCompleted += handler; 
... 
_csr.ServiceClient.GetChartDataCompleted -= handler; 

你也可以讓它自行退訂(即,使得它當事件引發退訂):

YourDelegateType handler = null; 
handler = (se, ea) => 
    { 
     _cachedCharts = ea.Result; 
     ChartDataRetrieved(ea.Result); 
     if (action != null) 
      action.Invoke(); 
     _csr.ServiceClient.GetChartDataCompleted -= handler; 
     _csr = null; 
    }; 
_csr.ServiceClient.GetChartDataCompleted += handler; 
+0

這看起來很有希望,非常感謝! – Keller

1

不,你不能這樣做,因爲這是其提高GetChartDataCompleted事件,造成傳遞給事件處理程序的對象(作爲參考)的類。它將創建一個GetChartDataCompletedEventArgs - 不是extendedEventArgs

如果你想想看,它就像試圖實現它看起來像這樣的接口:

public interface IFoo 
{ 
    void Foo(object x); 
} 

,像這樣一類:

public class Bar : IFoo 
{ 
    // We don't care if someone calling IFoo wants to pass us something 
    // other than a string - we want a string, darn it! 
    public void Foo(string y) 
    { 
     Console.WriteLine(y.Length); 
    } 
} 

這顯然行不通..

Marc已經顯示了修復它的一種方法 - 但我也想指出,你應該可能實際上只是要刪除代表當事件發生時。我假設該方法被稱爲GetChartDataAsync這一事實意味着它是一種非阻塞方法......因此在調用它之後立即退出事件可能不是一個好主意。

0

如果您更願意避免匿名方法,你可以手動執行基本上就是編譯器引擎蓋下爲你做。也就是說,創建一個閉包類來保存Action,並將其自身引用爲字段,並公開要分配給該事件的方法。事情是這樣的:

class RetrieveDataClosure 
{ 
    private Action action; 
    private MyClass self; 

    public RetrieveDataClosure(Action action, MyClass self) 
    { 
     this.action = action; 
     this.self = self; 
    } 

    public void ChartDataCompleted(object se, MyEventArgs ea) 
    { 
     self._cachedCharts = ea.Result; 
     self.ChartDataRetrieved(ea.Result); 
     if (action != null) 
     action.Invoke(); 
     self._csr = null; 
    } 
} 

,你會在你的代碼中使用這樣的:

var closure = new RetrieveDataClosure(action, this); 
_csr = new CustomerServiceRepository(); 
_csr.ServiceClient.GetChartDataCompleted += closure.ChartDataCompleted; 
_csr.ServiceClient.GetChartDataAsync( 
    Settings.Current.Customer.CustomerName, 
    pointId, 
    chartCollectionId); 
_csr.ServiceClient.GetChartDataCompleted -= closure.ChartDataCompleted; 
+0

儘管如果我是你,我會和Marc的自我取消回答一起去...... – gzak