6

私のニーズ

社内の標準製品で、事態が発生したときにさまざまなイベントを発生させたいと思います。さまざまなカスタムソリューションのグローバルasaxで、必要に応じてこれらのイベントに接続し、対応したいと思います。

既存のモジュール

asp.netのイベントアグリゲーターを探していましたが、何を使用すればよいかわかりません。Prismについて読んだことがありますが、これはasp.netではなくWPF/Silverlightを対象としているようです。

次に、WPFとは関係なく、アグリゲーターを自分のバージョンに移植したように見えるこの男がいます:http ://weblogs.asp.net/rashid/archive/2009/03/05/use-event-aggregator-to- make-your-application-more-extensible.aspx

質問

asp.netのイベントアグリゲーターを使用した経験はありますか?これは本番用であるため、ネット上のランダムな男からのホームコード化されたアグリゲーターを使用しないことを好みます:)

前もって感謝します。

編集1: NServiceBusは目的のために少しやり過ぎだったようです。トリックを実行する単一のEventAggregatorクラスを作成しました。

クラス:

/// <summary>
/// A event aggregator.
/// </summary>
public class EventAggregator
{
/// <summary>The object to use when locking.</summary>
private readonly object _lock = new object();
/// <summary>Holder of registered event handlers</summary>
private readonly Dictionary<Type, List<object>> _handlers = new Dictionary<Type, List<object>>();
/// <summary>Registers the specified handler.</summary>
/// <typeparam name="T"></typeparam>
/// <param name="handler">The handler.</param>
public void Register<T>(EventHandler<T> handler) where T : EventArgs
{
    lock (_lock)
    {
        if (!_handlers.ContainsKey(typeof (T)))
            _handlers.Add(typeof (T), new List<object>());
        _handlers[typeof (T)].Add(handler);
    }
}
/// <summary>Publishes the specified event.</summary>
/// <typeparam name="T"></typeparam>
/// <param name="sender">The sender.</param>
/// <param name="eventToPublish">The event to publish.</param>
public void Publish<T>(object sender, T eventToPublish) where T : EventArgs
{
    lock (_lock)
    {
        if (!_handlers.ContainsKey(typeof (T)))
            return; // No listers for event
        foreach (EventHandler<T> handler in _handlers[typeof (T)])
            handler.Invoke(sender, eventToPublish);
    }
}
}

イベントクラス:

public class EntityDeleted : EventArgs
{
}

グローバルasaxへのイベントハンドラーの登録:

aggregator.Register<EntityDeleted>((s, e) => {
// Do stuff here
});

イベントの発生:

aggregator.Publish(this, new EntityDeleted());

編集2:

そして、これが関心のあるもののための私のユニットテストです:

/// <summary>
/// Unit tests for EventAggregator
/// </summary>
[TestClass]
public class EventAggregatorTest
{
    /// <summary>Tests that no exceptions are thrown when calling an event with no handlers.</summary>
[TestMethod]
public void EmptyAggregatorTest()
{
    var aggregator = new EventAggregator();
    aggregator.Publish(this, new TestEventOne() { Property = "p1" });
}
/// <summary>Tests the aggregator using a single, registered handler.</summary>
[TestMethod]
public void SingleListenerTest()
{
    var aggregator = new EventAggregator();
    int calls = 0;
    aggregator.Register<TestEventOne>((sender, e) =>
    {
        Assert.AreEqual("p1", e.Property);
        calls ++;
    });
    Assert.AreEqual(0, calls);
    aggregator.Publish(this, new TestEventOne(){Property = "p1"});
    Assert.AreEqual(1, calls);
}

/// <summary>Tests the aggregator using multiple registered handlers.</summary>
[TestMethod]
public void MultipleListenersTest()
{
    var aggregator = new EventAggregator();
    int p1Calls = 0;
    int p2Calls = 0;
    aggregator.Register<TestEventOne>((sender, e) =>
    {
        Assert.AreEqual("p1", e.Property);
        p1Calls++;
    });
    aggregator.Register<TestEventOne>((sender, e) =>
    {
        Assert.AreEqual("p1", e.Property);
        p1Calls++;
    });
    aggregator.Register<TestEventTwo>((sender, e) =>
    {
        Assert.AreEqual("p2", e.Property);
        p2Calls++;
    });
    Assert.AreEqual(0, p1Calls);
    aggregator.Publish(this, new TestEventOne() { Property = "p1" });
    Assert.AreEqual(2, p1Calls);
    Assert.AreEqual(0, p2Calls);
    aggregator.Publish(this, new TestEventTwo() { Property = "p2" });
    Assert.AreEqual(1, p2Calls);
    Assert.AreEqual(2, p1Calls);
}
}

/// <summary>
/// Dummy test event 1
/// </summary>
public class TestEventOne : EventArgs
{
    public string Property { get; set; }
}
/// <summary>
/// Dummy test event 2
/// </summary>
public class TestEventTwo : EventArgs
{
    public string Property { get; set; }
}

編集3:

アグリゲーターがスレッドセーフではないことを指摘してくれたStevenRobbinsのおかげで、PublishメソッドとRegisterメソッドにロックを追加しました。

4

2 に答える 2

2

同様の要件がありました。このために、大きなコミュニティと優れたドキュメントを備えたオープンソースのNServiceBusを使用して、このリンクを試してください。

http://docs.particular.net/

于 2011-10-21T12:13:50.443 に答える
1

EAに単純な(単一のcsファイル)ドロップが必要な場合は、ホームロールのものよりも少し多くなります(上記のものはスレッドセーフではないようです。それが問題かどうかはわかりません)。TinyMessengerを見てください。

于 2011-10-24T10:49:46.913 に答える