WPFアプリケーション用の単純なメディエーターを作成しました(これは、ここにあるコードの派生物です)。
public class Messenger
{
private IDictionary<Type, IList<MessageObserver>> observers;
public Messenger()
{
observers = new Dictionary<Type, IList<MessageObserver>>();
}
public IDisposeObserver AddObserver<TMessageType>(Action<TMessageType> handler)
where TMessageType : Message { }
protected abstract void RemoveObserver<TMessageType>(Action<TMessageType> handler)
where TMessageType : Message { }
public abstract void PostMessage<TMessageType>(TMessageType message)
where TMessageType : Message { }
}
Message
は、を介して投稿されるすべてのメッセージの基本クラスを提供する単なる空のクラスですMessenger
。このクラスから派生して、関連データを含む特定のメッセージクラスを作成するという考え方です(少し似ていますEventArgs
)。
私の実装が異なるのは、オブザーバーを削除したい方法です。次の行に沿って、宣言的な方法でいつ削除する必要があるかを指定できるようにしたいと思います。
MessengerInstance.AddObserver<LoginMessage>(HandleLogin)
.RemoveObserverWhen(message => message.LoginResult == LoginResult.Successful);
RemoveObserverWhen
メソッドは、メソッドで指定されたメッセージタイプである必要がある場所をPredicate<T>
取ります。T
AddObserver
ここでの考え方は、オブザーバー自体を登録するのと同じ場所でオブザーバーを削除するロジックを指定できるということです。次に、Messengerクラスは、メッセージハンドラーの実行後に述語をチェックし、述語がtrueと評価された場合は、メッセージハンドラーと削除ハンドラーの両方を削除します。
各メッセージハンドラーは任意の数の削除ハンドラーを持つことができるので、これをと呼ばれるクラスにパッケージ化しましたMessageObserver
。
public class MessageObserver : IDisposeObserver
{
private IList<object> disposalHandlers;
public MessageObserver(object observer)
{
Observer = observer;
disposalHandlers = new List<object>();
}
public object Observer { get; private set; }
public IList<object> DisposalHandlers
{
get { return disposalHandlers; }
}
public IDisposeObserver RemoveObserverWhen<T>(Predicate<T> predicate)
where T : Message
{
disposalHandlers.Add(predicate);
return this;
}
}
メソッドを提供するMessageObserver
実装。IDisposeObserver
RemoveObserverWhen
public interface IDisposeObserver
{
IDisposeObserver RemoveObserverWhen<T>(Predicate<T> predicate)
where T : Message;
}
ここでの考え方は、IDisposeObserver
メソッドをチェーンできるようにインスタンスを返すことができるということです。
これはすべて機能し、viewModelに次のコードがあります。
MessengerInstance.AddObserver<LoginMessage>(HandleLogin)
.RemoveObserverWhen<LoginMessage>(message => message.LoginResult == LoginResult.Successful)
.RemoveObserverWhen<LoginMessage>(SecondDisposalHandler);
私が抱えている問題は、メソッドを呼び出すときにジェネリックパラメーター(LoginMessage
この場合)を指定した場合にのみこれが機能することです。RemoveObserver
投稿の冒頭で説明した方法でメソッドを呼び出せるようにしたいと思います。
どういうわけかジェネリックを返す必要があると思いますIDisposeObserver
が、この変更を行う場合はジェネリックにする必要があり、クラスが非ジェネリックでMessageObserver
あるため、制約を指定できません。Messenger
だから私の質問は、メソッドを呼び出すときにメッセージタイプを指定する必要がないようにコードを更新できますか、RemoveObserverWhen
それとも現在のソリューションを使用する必要がありますか?
注:これには他にも利用可能な実装があることは承知していますが、c#のオブジェクト指向設計の原則とジェネリックスを理解するためにこれを行っているので、他の実装の方向に向けないでください。