2016-12-16 90 views
1

我試圖執行請求/ Rebus的答覆,但也使用溫莎容器NuGet包:https://github.com/rebus-org/Rebus.CastleWindsorRebus的溫莎容器和inlinemessage搬運

查看以下樣品後:

https://github.com/rebus-org/RebusSamples/tree/master/RequestReply

https://github.com/rebus-org/RebusSamples/tree/master/Integration

我把這個例子拼湊在一起:

public class ContactModule : NancyModule 
{ 
    public ContactModule(IBus bus) 
    { 
     Get["/v1/contact"] = parameters => 
     { 
      var contacts = new List<Contact>(); 

      using (var activator = new BuiltinHandlerActivator()) 
      { 
       var settings = new Settings(); 

       activator.Handle<GetContactsResponse>(response => 
       { 
        contacts = response.Contacts; 

        return Task.FromResult(0); 
       }); 

       Configure.With(activator) 
        .Logging(l => l.ColoredConsole(LogLevel.Warn)) 
        .Transport(t => t.UseRabbitMq(
         settings.RabbitMQConnectionString, 
         settings.OutputQueueName)) // we listen for messages in the output queue 
        .Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName)) // but we publish to the input queue 
        .Options(o => 
        { 
         o.EnableCompression(); 
         o.EnableEncryption(settings.MessageEncryptionKey); 
        }) 
        .Start(); 

       activator.Bus.Publish(new GetContactsRequest``()).Wait(); 
      } 

      return Response.AsJson(contacts); 
     }; 
    } 
} 

我知道使用溫莎容器的方法時,它應該看起來可能更像下面,但我不懂得去傾聽的答覆:

public class ContactModule : NancyModule 
{ 
    public ContactModule(IBus bus) 
    { 
     Get["/v1/contact"] = parameters => 
     { 
      var contacts = new List<Contact>(); 

      bus.Publish(new GetContactsRequest()).Wait(); 

      // How do I listen for the reply? 

      return Response.AsJson(contacts); 
     }; 
    } 
} 

我的消息處理程序:

public class GetContactsHandler : IHandleMessages<GetContactsRequest> 
{ 
    private readonly IBus _bus; 
    private readonly Settings _settings; 

    public GetContactsHandler(IBus bus, Settings settings) 
    { 
     _bus = bus; 
     _settings = settings; 
    } 

    public async Task Handle(GetContactsRequest request) 
    { 
     // Fetch contacts from db... 
     var contacts = new List<Contact>(); 
     await _bus.Reply(new GetContactsResponse {Contacts = contacts}); 
    } 
} 

我的Rebus Windsor安裝程序:

public class RebusInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     var settings = new Settings(); 

     Configure.With(new CastleWindsorContainerAdapter(container)) 
      .Logging(l => l.ColoredConsole(LogLevel.Warn)) 
      .Transport(t => t.UseRabbitMqAsOneWayClient(
       settings.RabbitMQConnectionString)) 
      .Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName)) 
      .Options(o => 
      { 
       o.EnableCompression(); 
       o.EnableEncryption(settings.MessageEncryptionKey); 
      }) 
      .Start(); 
    } 
} 

我面對的問題是我想要我們e我的web api中的請求/回覆模式請求聯繫人列表,等待包含檢索到的聯繫人的回覆並將它們返回給api調用者。

但是,如果我想爲Rebus使用Windsor容器適配器,則IHandlerActivator接口不公開允許註冊內聯消息處理程序的.Handle方法,其中我從回覆中抓取聯繫人,然後將它們發回給api調用者。

有沒有辦法做到這一點,或者我不正確地接近問題?

編輯:正如你在第一個例子中看到的,我從Windsor容器的IBus接口注入。 但是,如果我使用注入的總線,我該如何告訴它來監聽從消息處理程序返回的回覆?

更新:Rebus.Async正是我一直在尋找:https://github.com/rebus-org/Rebus.Async

回答

2

當您正在使用一個真正的IoC容器,你應該創建一個實現IHandleMessages<TMessage>類,例如像這樣:

​​

爲你添加處理程序,並協助應用和域名服務,你的程序,它擴展好得多。

這當然意味着您必須攜帶Rebus.CastleWindsor NuGet包並將WindsorContainerAdapter傳遞給Rebus的.With(...)方法。

當你需要在溫莎註冊處理程序,您可以從Rebus.CastleWindsor擴展方法,它允許做這些事情的優勢:

// register all handler types from this assembly 
windsorContainer.AutoRegisterHandlersFromThisAssembly(); 

// register all handler types from typeof(SomeHandler).Assembly 
windsorContainer.AutoRegisterHandlersFromAssemblyOf<SomeHandler>(); 

// register one particular type as a message handler 
windsorContainer.RegisterHandler<GetContactsRequestHandler>(); 

你添加一些更多的信息更新後 - 你說:

(...)還是我錯誤地接近問題?

並且我會說「是」,因爲服務總線在同步請求/回覆方面不是很好 - 您應該使用「請求/回覆導向」的內容。 HTTP(*)。

而且 - 我幾乎一無所知南希,但我敢肯定,

bus.Publish(...).Wait(); 

就會死鎖,至少如果你在ASP.NET主機南希。

你應該總是

await bus.Publish(...); 

時,你可以,並在南希你可以這樣做:

Get["/v1/contact"] = async (parameters, ct) => 
{ 
    (...) 

    await bus.Publish(...); 

    (...) 
}; 

PS:最後一件事:請記住,保持容器周圍,只要因爲您希望端點處理消息。

在您發佈的代碼中,您在發佈該事件後立即處置了BuiltinHandlerActivator,這意味着您很可能根本無法處理任何消息。

如果您使用溫莎,公交車將在您處理溫莎集裝箱時處置。


(*)雖然滷麪也確實有Rebus.Async這是一個可以在您的方案中使用的請求/響應API。

我不會推薦走這條路。你可能應該這樣做,如果你打算這樣做一次,然後再也不會:) :)

+0

首先,我想說,感謝你這麼簡潔快速的答覆,我真的很感謝你的時間和精力。 您是否認爲使用Rebus進行分發工作比如創建資源並異步執行,然後使用HTTP檢索資源更好? 混合通信方法似乎是一種恥辱,我喜歡使用總線來實現我堆棧中所有內部通信的想法。 – Jam

+0

是的 - Rebus(以及這種類型的消息庫一般)是用於以可靠的方式異步處理事物,這通常使得它們比發出HTTP請求更慢。 – mookid8000

+0

因此,如果要確保處理消息中捕獲的信息,並且希望在發生錯誤時重新嘗試處理,則應該使用總線。 – mookid8000