TL;DR コントラクト サブスクリプションでは、動的プロキシではなく、生のメッセージ コンテンツまたは元の公開オブジェクトを取得するにはどうすればよいですか?
MassTransit に基づいてモジュラー アプリケーションを作成しようとして、うまくいきません。
私の考えは、Websocket サーバーをキューに接続し、ソケットからイベントを読み取り、「接続要求」としてキューに挿入し、キューからイベントを読み取り、「接続イベント」としてソケットに送信することです。両方とも、WS サーバーがイベントの送信先の接続と、システムの残りの部分の送信元を認識できるようにするコントラクトがあります。
public interface IConnectionRequest
{
String ConnectionId { get; set; }
}
public interface IConnectionEvent
{
String ConnectionId { get; set; }
}
セッションやその他のデータを維持するオブジェクトがあります。このオブジェクトは、リクエスト (アクション リクエストやサブスクリプション リクエストなど) を受け入れ、リクエストの結果として、または単に状態が変化したためにイベントをプッシュします。特定のイベントまたは一連のイベントをリッスンし、状態に対してアクションを実行するオブジェクトを作成したいので、次のコントラクトを作成しました。
public interface IConnectionRequestHandler<T> : Consumes<T>.Selected
where T : class, IConnectionRequest
{
}
たとえば、サーバーで実際のセッションを作成し、セッションの準備ができたときに通知する接続に応答するハンドラーを作成したいと考えています。リクエストを表すオブジェクトを作成し、その他のイベントとハンドラー自体を作成します。
public class CreateSessionRequest : IConnectionRequest
{
public String ConnectionId { get; set; }
}
public class CreatedSessionEvent : IConnectionEvent
{
public String ConnectionId { get; set; }
public Guid SessionId { get; set; }
}
public class CreateSessionEventHandler : IConnectionRequestHandler<CreateSessionRequest>
{
IServiceBus _bus;
public CreateSessionEventHandler(IServiceBus bus)
{
_bus = bus;
}
public bool Accept(CreateSessionRequest message)
{
return true;
}
public void Consume(CreateSessionRequest message)
{
// do stuff, create the session
var evt = new CreatedSessionEvent() { SessionId =Guid.NewGuid(), ConnectionId = message.ConnectionId };
_bus.Publish(evt, evt.GetType());
}
}
ここで、テスト目的で、シナリオをエミュレートする次のコードを作成します。基本的に、通信バスを作成し、リクエスト ハンドラをサブスクライブします。
var bus = ServiceBusFactory.New(sbc =>
{
sbc.ReceiveFrom("loopback://localhost/queue");
});
bus.SubscribeInstance<CreateSessionEventHandler>(new CreateSessionEventHandler(bus));
次に、Websocket サーバーをシミュレートして、WS から読み取ってキューに送信する部分を作成します。
IConnectionRequest e = new CreateSessionRequest() { ConnectionId = "myId" };
bus.Publish(e, e.GetType());
そして、キューからイベントを受信し、適切な接続に転送することになっている部分:
bus.SubscribeHandler<IConnectionEvent>(evt => Console.WriteLine("Sending event '{0}' to connection: {1}",
evt.GetType().Name,
evt.ConnectionId));
しかし、この最後の部分は期待どおりに機能しません。サブスクリプションで取得したオブジェクトは元のイベントではなく、動的なプロキシDynamicImpl.IConnectionEvent
であるため、のメンバーのみが含まれるため、このオブジェクトを JSON でシリアル化できませんIConnectionEvent
。
サブスクリプションでタイプを指定すると、次のように機能します。
bus.SubscribeHandler<CreatedSessionEvent>(evt => Console.WriteLine("Sending event '{0}' to connection: {1}",
evt.GetType().FullName,
evt.ConnectionId));
しかし、新しいイベントごとに、Websocket サーバーにアクセスしてその新しいタイプを登録する必要があることを意味します。
これを回避する方法はありますか?