2011-09-09 9 views
0

リファクタリングする必要があるコードに問題があります。今はlambdaをイベントハンドラとして使用していますが、適切に削除されません。私が読んだことから、これは可能でもありませんか?とにかく、無名関数の代わりに代理人を使用するように書き直したいのですが、今は問題はそれがパラメータとしてアクションを取ることです。私の新しい問題にアクションを渡す方法を理解できないようですデリゲート。これはコードです:イベントハンドラの引数にアクションを追加するC#

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; 
     } 

と拡張イベント引数にパラメータとしてアクションを渡すが、私は使用しようとすると:

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; 
                  }; 
     } 

私は多分、私は次のように作成することができると考えていましたそれがこの

_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イベントを発生させるクラスですので、いいえ、あなたはこれを行うことはできません。 extendedEventArgsではなくGetChartDataCompletedEventArgsが作成されます。

あなたが考えてみれば、それはこのようになりますインターフェイスを実装しようとしているようなものだ。このようなクラスで

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は1つの方法で固定していますが、実際にはのみ削除するようにしてください代理人イベントが発生したとき。私は、このメソッドがGetChartDataAsyncと呼ばれているということは、それがノンブロッキングメソッドであることを意味していると仮定しています。それを呼び出した直後のイベントからの脱退はおそらく素晴らしい考えではありません。

0

匿名メソッドを避けることを好むだろう場合は、手動コンパイラはボンネットの下に、あなたのために何をしているか、本質的に行うことができます。つまり、アクションを保持するクロージャークラスを作成し、フィールドとしての自身への参照を作成し、イベントに割り当てるメソッドを公開します。このような何か:

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

私があなただったら私はマークの自己解読解答に行きますが... – gzak

関連する問題