クラスの非ジェネリック インターフェイスとジェネリック インターフェイスがある設計パターンがあります (これが一般的に使用される DP かどうかは不明です。誰かがその名前を持っている場合はお知らせください)。実装はジェネリック値を格納し、ジェネリック インターフェイスを暗黙的に実装します。また、各プロパティが非ジェネリック形式に適切にキャストされたジェネリック プロパティの値を返す非ジェネリック インターフェイスを明示的に実装します。これはプロパティに対しては非常にうまく機能しますが、イベントに対してもうまく機能させるにはいくつか問題があります。
以下は、私がやっていることの非常に単純化されたバージョンです。Event のいずれかのインターフェイス バージョンにハンドラーを追加すると、それを同じイベントに追加して、イベントが発生したときにサブスクライブされた方法が問題にならないようにするという考え方です。Main のテスト コードは、イベント ハンドラーが期待どおりに削除されていないことを示しています。INormalInterface.Event の追加/削除ブロックを使用してイベントに追加/削除するための正しいコードは何ですか?
class Program
{
static void Main(string[] args)
{
INormalInterface x = new ImplementingClass<int>();
Console.WriteLine("Created x and invoking...");
x.InvokeEvent();
Console.WriteLine("Adding event and invoking...");
x.Event += x_Event;
x.InvokeEvent();
Console.WriteLine("Removing event and invoking...");
x.Event -= x_Event;
x.InvokeEvent();
Console.WriteLine("Done.");
Console.ReadKey(true);
}
static void x_Event(object sender, NormalEventArgs e)
{
Console.WriteLine("Event Handled!");
}
}
interface INormalInterface
{
event EventHandler<NormalEventArgs> Event;
void InvokeEvent();
}
interface IGenericInterface<T> : INormalInterface
{
new event EventHandler<GenericEventArgs<T>> Event;
}
class ImplementingClass<T> : IGenericInterface<T>
{
public event EventHandler<GenericEventArgs<T>> Event;
event EventHandler<NormalEventArgs> INormalInterface.Event
{
add { Event += new EventHandler<GenericEventArgs<T>>(value); }
remove { Event -= new EventHandler<GenericEventArgs<T>>(value); }
}
public void InvokeEvent()
{
if (Event != null)
{
Event(this, new GenericEventArgs<T>());
}
}
}
class NormalEventArgs : EventArgs
{
}
class GenericEventArgs<T> : NormalEventArgs
{
}
問題は、デリゲートを毎回「新しく」作成しているため、追加/削除時に同じ値に解決されないためだと思います。デリゲートをキャストする方法はありますか? 私には1つの解決策がありますが、各イベントにフィールドが必要なので、これを回避する解決策をいただければ幸いです:
class ImplementingClass<T> : IGenericInterface<T>
{
private readonly Dictionary<EventHandler<NormalEventArgs>, EventHandler<GenericEventArgs<T>>> m_eventDictionary = new Dictionary<EventHandler<NormalEventArgs>, EventHandler<GenericEventArgs<T>>>();
public event EventHandler<GenericEventArgs<T>> Event;
event EventHandler<NormalEventArgs> INormalInterface.Event
{
add { Event += m_eventDictionary[value] = new EventHandler<GenericEventArgs<T>>(value); }
remove { Event -= m_eventDictionary[value]; }
}
public void InvokeEvent()
{
if (Event != null)
{
Event(this, new GenericEventArgs<T>());
}
}
}