ここに質問を置きます:複数のサブスクライバーに対してドメイン イベントを発生させると、その答えにより、次のような IEventPublisher を持つことができるパターンにたどり着きました。
public interface IEventPublisher<T>
{
void Publish(T data);
}
および IEventSubscriber は次のようになります。
public interface IEventSubscriber<T>
{
void Handle(T data);
}
これに関する問題は、次のように各パブリッシャーのインスタンスをコンストラクターに渡す必要があることです。
public Service(IEventPublisher<ThingyChangedEvent> publisherThingyChanged)
{
// Set publisher to local variable
}
// then call this in a method
_publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});
私が理想的にできることは、IEventPublishers を含むジェネリック パブリッシャーを持つことで、次のようなものを呼び出すことができます。
_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});
この例のように T を ThingyChangedEvent として定義せずに IEventPublisher のコレクションを渡すことはできないため、これを行う方法を理解できませんが、汎用パブリッシャーに渡されるタイプに基づいてパブリッシャーを決定する必要があります。 .
どんな提案でも大歓迎です。
編集:
以下の回答とここからの情報を使用してOK :http://www.udidahan.com/2009/06/14/domain-events-salvation/
public interface IEventManager
{
void Publish<T>(T args) where T : IEvent;
}
public class EventManager : IEventManager { Autofac.ILifetimeScope _container;
public EventManager(Autofac.ILifetimeScope container)
{
_container = container;
}
//Registers a callback for the given domain event
public void Publish<T>(T args) where T : IEvent
{
var subscribersProvider = _container.Resolve<IEventSubscribersProvider<T>>();
foreach (var item in subscribersProvider.GetSubscribersForEvent())
{
item.Handle(args);
}
}
}
これで、autofac によって解決されたコンストラクターで IEventManager eventManager のインスタンスを取得し、次のように呼び出すことができます。
_eventManager.Publish<ThingyChangedEvent>(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
このソリューションについて私が気に入らない点は次のとおりです。
コンストラクターで ILifetimeScope のインスタンスを取得したくありません。IEventSubscribersProvider のコレクションを取得できるようにしたいのですが、次のように要求すると、autofac はこれを解決しません。
IEnumerable<IEventSubscribersProvider<IEvent>>
タイプをパブリッシュに渡して呼び出す場合にのみ解決できます。
Resolve<IEventSubscribersProvider<T>>.
2 番目の問題は大した問題ではありませんが、次のように型を渡さずに publish を呼び出せると便利です。
_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
これら 2 つの問題、特に問題 1 を解決する方法について何か提案があれば、別のプロジェクトで Autofac に依存するのは好きではないので、私は思います。私が思いつくことができる唯一のものは、次のように明示的に必要なものを取るある種のマネージャークラスです:
public SomeConstructor(
IEventSubscribersProvider<ThingyChangedEvent> thingChangedSubscribeProviders,
IEventSubscribersProvider<SomeOtherEvent> someOtherSubscribeProviders,
etc....)
{
// Maybe take the EventManager as well and add them to it somehow but would be
// far easier to take a collection of these objects somehow?
}
ご提案いただきありがとうございます。
編集2
多くの調査を行い、実行時にこの Autofac Generic Service の解像度を調べた後、私が望むことを達成できるかどうかはわかりません。私が思いつく最善の解決策はこれです:
public interface IEventSubscribersProviderFactory : Amico.IDependency
{
IEventSubscribersProvider<T> Resolve<T>() where T : IEvent;
}
public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory
{
Autofac.ILifetimeScope _container;
public EventSubscribersProviderFactory(Autofac.ILifetimeScope container)
{
_container = container;
}
public IEventSubscribersProvider<T> Resolve<T>() where T : IEvent
{
return _container.Resolve<IEventSubscribersProvider<T>>();
}
}
次に、EventManager にコンストラクターで IEventSubscribersProviderFactory を取得させ、そのプロジェクトから Autofac への依存関係を削除します。
今のところこれで行きますが、長期的にはより良い解決策が見つかることを願っています.