3

内部オブジェクトのイベントをサブスクライブする場所を決定する必要がある状況に頻繁に遭遇しますか?

たとえば、次のようなオブジェクトモデルがあります。

class ClassA
{
    public event EventHandler SomeEvent1;
    public event EventHandler SomeEvent2;
    public event EventHandler SomeEvent3;
    public event EventHandler SomeEvent4;
}

class ClassB
{
    private ClassA a;
    public ClassA A 
    {
        get
        {
            return this.a;
        }
    }

    public ClassB()
    {
        this.a = new ClassA();
        // here subscribe to some events (for example, SomeEvent1 and SomeEvent2)
        // this.a.SomeEvent1 += OnSomeEvent1Raised;
        // this.a.SomeEvent2 += OnSomeEvent2Raised;
    }
}

class ClassC
{
    public ClassB B { get; }
}

class ClassD
{
    public ClassC C { get; }

    public void SomeMethod()
    {
        // Here subscribe to another ones events of object C.B.A. For example:
        C.B.A.SomeEvent3 += OnSomeEvent3Raised;
        C.B.A.SomeEvent4 += OnSomeEvent4Raised;
    }

    private void OnSomeEvent4Raised(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    private void OnSomeEvent3Raised(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

私はUML図のようなものを作成しようとしました: ここに画像の説明を入力してください

私のプロジェクトの既存のコードの構造には、そのようなオブジェクトモデルが存在する場所があります(上記の例のように実装されたイベントをサブスクライブする場所があります-CBASomeEvent + =)。私はそれが好きではなく、それを変更したいと思います。この状況に関するベストプラクティスをここに示したいと思います。

別のアプローチは、classB、classC、classDのclassAのすべてのイベントを複製することです。次に、イベントへのすべてのサブスクリプションを1つの場所に置き換えます(つまり、classBでは、ClassAのオブジェクトのすべてのイベントをサブスクライブ/サブスクライブ解除します。classCでは、classBのオブジェクトのすべてのイベントをサブスクライブ/サブスクライブ解除します on ...)この場合、すべてのサブスクリプションとサブスクリプション解除は1か所になります。私がここで何を意味するのか理解していただければ幸いです。

繰り返しになりますが、あなたの知識と経験に頼って、この状況を解決する方法を教えてください。

アップデート

イベントのサブスクリプションとサブスクリプション解除は1つの場所に配置する必要があることに同意しますか?この追加の質問にも答えてください。

前もって感謝します。

4

3 に答える 3

2

イベントアグリゲーターに興味があるかもしれません。

基本的には、パブリッシャーをサブスクライバーから切り離すことです。これは一種のイベントコンテナーです。サブスクライブまたは公開するクラスごとに、依存性注入(MEFなど)を介してイベントアグリゲーターを取得できます。

私が個人的に使用し、最も気に入っている方法は、RobEisenbergがCaliburnMicroにイベントアグリゲーターを実装した方法です。

あなたの場合、オブジェクトA、B、Cはイベントアグリゲーターの同じインスタンスを共有します。つまり、このイベントアグリゲーターでイベントが公開されるとすぐに、これらすべてのオブジェクトがそれを認識します。クラスA、B、およびCは、特定のイベントの処理が異なるため、動作が異なる可能性があります。

編集

イベントアグリゲーターの使用法は、クラスのインスタンスを使用してアグリゲーター自体をサブスクライブすることです。パブリッシャークラスとサブスクライバークラスの間の接続は、イベントアグリゲーターの同じインスタンスに依存することで発生します。Caliburn.Microの場合、特定のイベントへのサブスクリプションは、汎用インターフェイス(IHandle<>)を実装することで発生します。例:サブスクライブする場合は、サブスクライブするクラスにインターフェイスMyCustomEventを実装します。これには、このタイプのイベントのインターフェースからメソッドをIHandle<MyCustomEvent>実装する必要があります。このメソッドは、(新しい)が共有イベントアグリゲーターで公開されるたびに呼び出されます。void Handle(MyCustomEvent e)IHandle<MyCustomEvent>MyCustomEvent

于 2013-01-23T12:41:07.807 に答える
0

あなたの例にはあまりにも多くのpublicものがあります。私が以下で意味をなすことを願っています:

  1. ClassBには、ClassAタイプのオブジェクトが含まれ、いくつかのClassAイベントを処理します
  2. ClassCにはClassBタイプのオブジェクトが含まれていますが、イベントは無視されます。
  3. ClassDには、ClassCタイプのオブジェクトが含まれ、このClassCオブジェクトに含まれるClassBオブジェクト内のClassAオブジェクトからのイベントを処理します。

#2と#3は良くありません。ClassCはイベントを処理して実装し、それらを処理して、ClassDが正しく処理できるように「バブルアップ」(独自の同じイベントを呼び出す)できるようにする必要があります。

基本的に、それらはすべて、それらに反応するか(ClassBからClassAのイベントのように)、または単にそれらを伝播するかのいずれかで、すべてのイベントを処理する必要があります。

于 2013-01-23T13:28:10.427 に答える
0

ここで素晴らしい解決策を見つけてください:

Csharp-通知センター

于 2013-01-27T16:19:15.867 に答える