使用Ninject与EasyNetQ / RabbitMQ消息处理程序

时间:2014-11-04 20:51:21

标签: c# .net rabbitmq ninject easynetq

我正在尝试使用带有Ninject的EasyNetQ来记录消息。

我设法将Ninject设置为EasyNetQ DI(我认为),但是当一个消息来到没有无参数构造函数的处理程序时(例如我需要在那里绑定一个存储库),它就无法解决。或者至少我认为这是问题,因为我在控制台上得到了一个非常通用的错误。

我告诉EasyNetQ像这样使用Ninject:

RabbitHutch.SetContainerFactory(() => new NinjectAdapter(container));

我认为这就是我需要设置的全部内容。 Ninject适配器是EasyNetQ的适配器。

我的处理程序如下所示:

public class ProfileDeactivatedUpdateHandler : IConsume<ProfileDeactivatedUpdate>
{
    private readonly IProfileRepository _profileRepository;

    public ProfileDeactivatedUpdateHandler(IProfileRepository profileRepository)
    {
        _profileRepository = profileRepository;
    }

    public void Consume(ProfileDeactivatedUpdate message)
    { 
        //Do Stuff. 
    }
}

如果我添加一个无参数构造函数,而是通过ServiceLocator(Ugh)设置Ninject,那么它可以工作。处理程序被称为正常,我可以通过ServiceLocator找到我的存储库,所以我知道至少Ninject知道存储库。

尝试处理邮件时弹出的错误是。

System.AggregateException: One or more errors occurred. ---> System.Exception: E
xception of type 'System.Exception' was thrown.
   at EasyNetQ.ReflectionHelpers.DefaultFactories`1.Get()
   at EasyNetQ.ReflectionHelpers.CreateInstance[T]()
   at EasyNetQ.AutoSubscribe.DefaultAutoSubscriberMessageDispatcher.Dispatch[TMe
ssage,TConsumer](TMessage message)
   at EasyNetQ.RabbitBus.<>c__DisplayClass6`1.<Subscribe>b__5(T msg)
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.Exception: Exception of type 'System.Exception'
 was thrown.
   at EasyNetQ.ReflectionHelpers.DefaultFactories`1.Get()
   at EasyNetQ.ReflectionHelpers.CreateInstance[T]()
   at EasyNetQ.AutoSubscribe.DefaultAutoSubscriberMessageDispatcher.Dispatch[TMe
ssage,TConsumer](TMessage message)
   at EasyNetQ.RabbitBus.<>c__DisplayClass6`1.<Subscribe>b__5(T msg)<---

1 个答案:

答案 0 :(得分:4)

所以我已经解决了这个问题。显然,当EasyNetQ实例化处理程序时,它不会使用指定的DI框架来执行此操作(Boo!)。你必须指定一个&#34; MessageDispatcher&#34;单独实施。真棒!哦......但是......只有一个Autofac的实现,而不是Ninject(Boo!x2)。

所以,我的pull请求在这里是为Ninject实现事件调度程序的代码在这里: https://github.com/mikehadlow/EasyNetQ/pull/309

现在,您可以将该类复制并粘贴到项目中。然后在NinjectModule或设置绑定的任何地方,您可以执行以下操作:

//Bind Message Dispatcher to Ninject event message dispatcher
NinjectMessageDispatcher messageDispatcher = new NinjectMessageDispatcher(Kernel);
Bind<IAutoSubscriberMessageDispatcher>().ToConstant(messageDispatcher);

然后,无论您在何处设置订阅者,都可以执行以下操作(请注意,这是使用EasyNetQ的IConsume界面进行自动订阅。

var subscriber = new AutoSubscriber(_serviceBus, "ProfileServices");
subscriber.AutoSubscriberMessageDispatcher = _dispatcher;
subscriber.Subscribe(Assembly.GetExecutingAssembly());

重要的是将MessageDispatcher手动设置为ninject调度程序的实例。您希望如何实现这一目标取决于您。

我认为将来,EasyNetQ可能需要自动执行此操作。显然,如果你将工厂设置为使用Ninject,那么你的处理程序也可能想要使用Ninject。

哦!您可以修改上面的代码以使用您选择的DI。对于EasyNetQ(我认为)使用的任何DI都需要这样做,而不仅仅是Ninject。