0

問題:

私のドメイン層アセンブリには、次の 2 つのインターフェイスを格納しています。

public interface IDomainEvent { }

public interface IHandle<T> where T: IDomainEvent, new()

EventDispatcherクラスもそこで定義されています:

public static class EventDispatcher {
    [ThreadStatic]
    private static List<Delegate> actions;
    [ThreadStatic]
    private static List<Object> handlers;

    public static List<Object> Handlers { 
        get { return handlers; } 
        set { handlers = value; } 
    }

    public static void Register<T>(Action<T> callback) where T : IDomainEvent, new() {
        if(null == actions) {
            actions = new List<Delegate>();
            actions.Add(callback);
        }
    }

    public static void ClearCallbacks() {
        actions = null;
    }

    public static void Raise<T>(T @event) where T : IDomainEvent, new() {
        if(null != Handlers) {
            foreach(var handler in Handlers.Where(h => h is IHandle<T>)) {
                ((IHandle<T>)handler).Handle(@event);
            }
        }

        if(null != actions) {
            foreach(var action in actions) {
                if(action is Action<T>) {
                    ((Action<T>)action)(@event);
                }
            }
        } // if(null != actions) {
    }
}

プレゼンテーション層アセンブリにモジュールがあります:

public class EventDispatchingModule : NinjectModule {

    public override void Load() {

        // EventDispatcher.Handlers = this.Kernel.GetAll(IHandle<T>); Can't do that!
        // Bind<IHandle<CarHasBeenRegisteredEvent>>().To<CarHasBeenRegisteredHandler();
    }
}

パラメータKernel.GetAll(IHandle<T>)を解決できないため、そこを呼び出すことはできません。T

どうすればこれを解決できますか?

ありがとう!

4

2 に答える 2

2

モジュールを使用する必要はありません (私は ninject を使用していませんが、同様のものを使用しています):

// Put these in the domain project

public class EventDispatcher
{
    private static IEventDispatcher _dispatcher;

    public static void Setup(IEventDispatcher dispatcher)
    {
        _dispatcher = dispatcher;
    }

    public static void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        _dispatcher.Dispatch<T>(domainEvent);
    }
}

public interface IEventDispatcher
{
    public void Dispatch<T>(T domainEvent) where T : IDomainEvent;
}


// and this one in the project which has Ninject

public class NinjectEventDispatcher : IEventDispatcher
{
    private static IKernel _container;

    public NinjectEventDispatcher(IKernel container)
    {
        _container = container;
    }

    public void Dispatch<T>(T domainEvent) where T : IDomainEvent
    {
        foreach (var listener in _container.GetAll<IHandle<T>>())
        {
            listener.Handle(domainEvent);
        }
    }
}

// And after the container have been configured:
EventDispatcher.Setup(new NinjectEventDispatcher(_container));

しかし、ninject がスコープ オブジェクトをどのように処理するかはわかりません (イベントを受け取る必要がある場合もあります)。

私のコンテナにはドメイン イベントが組み込まれています。詳細については、次の記事を参照してください: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container

アップデート:

コード サンプルを更新して、ドメイン プロジェクトが Ninject を認識しないようにしました。

このコードで Service Location を使用していません。イベントディスパッチャの内部は. つまり、コードは影響を受けません。

于 2012-08-31T12:44:05.890 に答える
2

次のコードですべてのハンドラーを取得できます

Kernel.GetAll(typeof (IHandle<>));

ただし、別のモジュールが既にロードされているかどうかがわからないため (別のモジュールもハンドラーを登録できるため)、NInjectModule にすべての IHanders をロードすることはお勧めできません。EventDispatcher クラスを静的ではなく、必要なスコープに登録することをお勧めします (リクエストごとに新しいハンドラーが必要な場合は、リクエスト スコープで、それ以外の場合はシングルトン スコープで . コンストラクターで注入できるハンドラーは次のようになります。

Kerner.Bind<EventDispatcher>().ToSelf()
      .InRequestScope()
      .WithConstructorArgument("handlers", c => c.Kernel.GetAll(typeof(IHandler<>)))

お役に立てれば

于 2012-08-31T13:24:57.540 に答える