Silverlight 5 で動作する次のコードがあります。
public void Send(Notification notification)
{
// Because the variable is passed as Notification, we have to trick the
// type-inference feature of the runtime so the message will be sent using
// the actual type of the object.
// Using the dynamic keyword, we can convert the type of the object passed
// to the Send method.
// This allows subscribers to register for messages using the generic interface.
dynamic stronglyTypedNotification = Convert.ChangeType(notification,
notification.GetType(),
CultureInfo.InvariantCulture);
SendCore(stronglyTypedNotification);
}
private void SendCore<T>(T notification)
where T : Notification
{
foreach (var handlerFactory in Handlers)
{
var handler = handlerFactory.Value as INotificationHandler<T>;
if (handler != null)
{
handler.Handle(notification);
}
}
}
WPF アプリケーションで実行するには、このコードを移植する必要があります。
WPF アプリケーションで実行し、SendCore メソッド内にブレークポイントを設定すると、T は正しい型ではありません。これは、ジェネリックが静的に定義されているため、コンパイラが実行時に必要と思われるバージョンの SendCore を作成したためだと推測できます。このコードは SL で完全に機能するため、Silverlight ではこれを別の方法で処理していると思います。
このコードの目的は、INotificationHandler を実装する Handlers コレクションに含まれる任意のオブジェクトを見つけることです。ここで、T は Send メソッド (基本 Notification クラスをサブクラス化する) に渡されるオブジェクトの型であり、次に Handle(T n) メソッドを呼び出します。それらのオブジェクト。
私のWPFアプリでこれを行うにはどうすればよいですか?
アップデート
いくつかの追加テストの後、私はより独特な結果を見つけています。SendCore メソッドの最初の行にブレークポイントを設定し、T と通知を調べると、次のことがわかります。
- Intellisense は、T がアセンブリ内の正当なクラスである "GenericNotification" であることを示します。
- Intellisense は、「通知」が厳密に型指定された正しいクラス (DataChangedNotification) であることを示します。
- DataChangedNotification は、いかなる方法でも GenericNotification をサブクラス化しません。どちらも Notification のサブクラスです。
- T は GenericNotification に解決されるため、各ハンドラーを INotificationHandler<T> にキャストしようとしても、INotificationHandler<GenericNotification> を実装していないため失敗します。
この正確なコードが Silverlight、コンソール アプリケーション、および別の WPF アプリケーション (および LINQpad での David のテスト) で機能することを考えると、いったい何が起こっているのでしょうか?
私が言及できる唯一のことは、WPF アプリケーションによって参照されるクラス ライブラリにコードが実際に存在するということです。別の(新しい)WPFアプリケーションでそのシナリオをテストし、正しい結果が得られたため、それが問題かどうかはわかりません。