1

標準の ASP.NET MVC 3 Web アプリケーションがあります。

私はいくつかの分野横断的な懸念を持っており、いくつかの AOP、特にイベント ディスパッチャ パターンを採用したいと考えています。

たとえば、何かが発生したときにコントローラーで「イベントを発生させ」、アプリケーション (リポジトリ、サービスなど) にいくつかの「リスナー」を分散させて、このイベントをリッスンし、それに応じて動作させたいと考えています。

また、IoC コンテナーに StructureMap を使用していることにも言及する必要があります。そのため、イベント ディスパッチャーが IoC コンテナーに依存するのではなく、IoC コンテナーを使用する (またはプラグ可能である) 場合に最適です。

これを行うNuGetパッケージを見つけた人はいますか、それとも、その方法を説明した記事/質問を教えてもらえますか?

4

2 に答える 2

4

コントローラはステートレスであると想定されています。フレームワークは、要求が処理された後にコントローラーオブジェクトを破棄し、次の要求が来たときにそれを再作成します。実際、ASP.NET MVCは、要求ごとにコントローラーの個別のインスタンスを作成します。コントローラでイベントを宣言し、他のアプリケーションサービスでこのイベントをサブスクライブすると、メモリリークが発生する可能性があります(他の有効なオブジェクトからのコントローラへの有効な参照があるため、GCは使用済みのコントローラを破棄しません)。

また、IISは、アイドル状態になるか、その他の理由でWebアプリケーションのプロセスを強制終了する可能性があるため、Webアプリケーションもステートレスであると想定されていることに注意してください。

また、そのイベント処理の同時実行性にも留意する必要があります。

イベントのパブリッシュ/サブスクライバーパターンを使用できますが、別の「エージェント」として実装する必要があります。たとえば、Windowsサービスは、一部のポートをリッスンし、Webアプリケーションからの要求を処理します。

于 2012-09-03T06:45:30.007 に答える
0

私はあなたのコントローラーがイベントを発生させるべきではないと思います、それはあなたがあなたのドメイン固有の検証をした後あなたのドメインロジックのための何かであるべきです。検証を行って動作することを確認する前に、実際に何かが発生したことをどのように確認できますか?

ただし、単純なイベントベースのソリューションを実装することはそれほど難しくありません。私は次のようなものを選びます:

public abstract class BaseEvent {}

public class EventRouter {
            private Dictionary<Type, List<Action<BaseEvent>>> _eventRoutes;

    public EventRouter ()
    {
        _eventRoutes= new Dictionary<Type, List<Action<BaseEvent >>>();
    }

    public void Register<TEvent>(Action<TEvent> route) where TEvent : BaseEvent
    {
        List<Action<TEvent>> routes;
        var type = typeof(BaseEvent);
        if (_eventRoutes.TryGetValue(type, out routes).IsFalse())
        {
            routes = new List<Action<TEvent>>();
            _eventRoutes.Add(type, routes);
        }
        routes.Add((y) => route(y as BaseEvent));
    }

    public bool TryGetValue(Type commandType, out List<Action<TEvent>> handlers)
    {
        return _eventRoutes.TryGetValue(eventType, out handlers);
    }
}

public class InMemoryEventDispatcher : IEventBus
{
    private readonly IEventRouter _eventRouter;

    public InMemoryEventBus(IEventRouter eventRouter)
    {
        _eventRouter = eventRouter;
    }

    public void PublishEvent<TEvent>(TEvent @event) where TEvent : BaseEvent
    {
        var eventType = @event.GetType();
        List<Action<TEvent>> eventHandlers;
        if (_eventRouter.TryGetValue(eventType, out eventHandlers).IsTrue())
        {
            foreach (var eventHandler in eventHandlers)
            {
                eventHandler(@event);
            }
        }
    }

    public void PublishEvents<TEvent>(IEnumerable<BaseEvent> events) where TEvent : BaseEvent
    {
        foreach (var @event in events)
        {
            PublishEvent(@event);
        }
    }
}

これで、イベントごとに実行するアクションを登録できます。私はそれをコンパイルしていませんが、そのようなものが行くはずです。

于 2012-09-03T07:02:16.520 に答える