使用 topshelf.ninject 在模块中获取 ninject 内核
Getting ninject Kernel in a module with topshelf.ninject
我正在编写一项新服务,并且是第一次使用 Topshelf 和 EasyNetQ。我没有使用 MVC 或 WebAPI(大多数 ninject tutorials/blog 帖子似乎都假设了)。关键依赖项是 Topshelf、Ninject(单构建版本而不是 nugget 包)和 EasyNetQ。
我选择 ninject 是因为我在 MVC 项目中使用过它,并且 Topshelf.ninject 库可用。
因此,在设置 topshelf 时,我调用了 UseNinject 方法并传入了一个 Ninject 模块:
public static int Main(string[] args)
{
Thread.CurrentThread.Name = "Service Main Thread";
var exitCode = HostFactory.Run(x =>
{
x.UseNinject(new Prototype.Service.Modules.IocModule());
x.Service<SampleService>(s =>
{
s.ConstructUsingNinject();
s.WhenStarted((service, hostControl) => service.Start(hostControl));
s.WhenStopped((service, hostControl) => service.Stop(hostControl));
});
x.RunAsLocalSystem();
x.SetDescription("Prototype .NET Micro Service");
x.SetDisplayName(typeof(SampleService).Namespace);
x.SetServiceName(typeof(SampleService).Namespace);
x.UseNLog();
});
return (int) exitCode;
}
}
模块看起来像这样:
public class IocModule : NinjectModule
{
/// <summary>
/// Bind Interfaces to implimentations for dependancy injection
/// </summary>
public override void Load()
{
Bind<ISampleService>().To<SampleService>();
Bind<IAdvancedBus>().ToMethod(context => BusFactory.CreateMessageBus()).InSingletonScope();
Bind<IExchange>().ToMethod(context => ExchangeFactory.CreatExchange(Kernel.Get<IAdvancedBus>())).InSingletonScope();
Bind<IQueue>().ToMethod(context => QueueFactory.CreatQueue(Kernel.Get<IAdvancedBus>())).InSingletonScope();
Bind<ILogger>().To<Logger.Logger>().InSingletonScope();
Bind<IMessagePublisher>().To<MessagePublisher>();
Bind<IMessageConsumer>().To<MessageConsumer>();
Bind<ISubscriber>().To<SampleSubscriber>();
Bind<IAutoSubscriberMessageDispatcher>().To<MessageDispatcher>();
Bind(typeof(IRepository<>)).To(typeof(MongoRepository<>));
Bind<IHostingEnvironment>().To<HostingEnvironment>();
Bind<ISampleLogic>().To<SampleBusinessLogicClass>();
}
}
还有一个工厂:
public static class QueueFactory
{
public static IQueue CreatQueue(IAdvancedBus bus)
{
var queue = bus.QueueDeclare("QueueName");
return queue;
}
}
我的问题是 ninject 模块中 IExchange 和 IQueue 的绑定。如您所见,工厂方法需要 IAdvancedBus 的实例,但 Kernel 在运行时为空。我试图通过方法 args 传递依赖项,因为它是静态的 class,我无法通过构造函数注入。
正确的做法是什么?我似乎无法获得对 ninject 内核的引用,而且感觉不对。我觉得我正在掉进一个试图以错误的方式做这件事的兔子洞里。此外,内核被标记为已过时,我看不到另一种获取对象实例的方法。显然,我也不能像在 MVC 中那样使用依赖项解析器。
topshelf 是否有等效的依赖解析器?有更好的模式吗?不过,我做了什么来保持松散耦合,所以我想避免静态 classes、单例或任何其他迫使我陷入难以测试的具体依赖关系的东西。
有什么想法吗?
Ninject.IContext
(lambda 中的参数)引用了 IKernel
,因此更改为:
Bind<IQueue>().ToMethod(context => QueueFactory.CreatQueue(context.Kernel.Get<IAdvancedBus>())).InSingletonScope();
我正在编写一项新服务,并且是第一次使用 Topshelf 和 EasyNetQ。我没有使用 MVC 或 WebAPI(大多数 ninject tutorials/blog 帖子似乎都假设了)。关键依赖项是 Topshelf、Ninject(单构建版本而不是 nugget 包)和 EasyNetQ。
我选择 ninject 是因为我在 MVC 项目中使用过它,并且 Topshelf.ninject 库可用。
因此,在设置 topshelf 时,我调用了 UseNinject 方法并传入了一个 Ninject 模块:
public static int Main(string[] args)
{
Thread.CurrentThread.Name = "Service Main Thread";
var exitCode = HostFactory.Run(x =>
{
x.UseNinject(new Prototype.Service.Modules.IocModule());
x.Service<SampleService>(s =>
{
s.ConstructUsingNinject();
s.WhenStarted((service, hostControl) => service.Start(hostControl));
s.WhenStopped((service, hostControl) => service.Stop(hostControl));
});
x.RunAsLocalSystem();
x.SetDescription("Prototype .NET Micro Service");
x.SetDisplayName(typeof(SampleService).Namespace);
x.SetServiceName(typeof(SampleService).Namespace);
x.UseNLog();
});
return (int) exitCode;
}
}
模块看起来像这样:
public class IocModule : NinjectModule
{
/// <summary>
/// Bind Interfaces to implimentations for dependancy injection
/// </summary>
public override void Load()
{
Bind<ISampleService>().To<SampleService>();
Bind<IAdvancedBus>().ToMethod(context => BusFactory.CreateMessageBus()).InSingletonScope();
Bind<IExchange>().ToMethod(context => ExchangeFactory.CreatExchange(Kernel.Get<IAdvancedBus>())).InSingletonScope();
Bind<IQueue>().ToMethod(context => QueueFactory.CreatQueue(Kernel.Get<IAdvancedBus>())).InSingletonScope();
Bind<ILogger>().To<Logger.Logger>().InSingletonScope();
Bind<IMessagePublisher>().To<MessagePublisher>();
Bind<IMessageConsumer>().To<MessageConsumer>();
Bind<ISubscriber>().To<SampleSubscriber>();
Bind<IAutoSubscriberMessageDispatcher>().To<MessageDispatcher>();
Bind(typeof(IRepository<>)).To(typeof(MongoRepository<>));
Bind<IHostingEnvironment>().To<HostingEnvironment>();
Bind<ISampleLogic>().To<SampleBusinessLogicClass>();
}
}
还有一个工厂:
public static class QueueFactory
{
public static IQueue CreatQueue(IAdvancedBus bus)
{
var queue = bus.QueueDeclare("QueueName");
return queue;
}
}
我的问题是 ninject 模块中 IExchange 和 IQueue 的绑定。如您所见,工厂方法需要 IAdvancedBus 的实例,但 Kernel 在运行时为空。我试图通过方法 args 传递依赖项,因为它是静态的 class,我无法通过构造函数注入。
正确的做法是什么?我似乎无法获得对 ninject 内核的引用,而且感觉不对。我觉得我正在掉进一个试图以错误的方式做这件事的兔子洞里。此外,内核被标记为已过时,我看不到另一种获取对象实例的方法。显然,我也不能像在 MVC 中那样使用依赖项解析器。
topshelf 是否有等效的依赖解析器?有更好的模式吗?不过,我做了什么来保持松散耦合,所以我想避免静态 classes、单例或任何其他迫使我陷入难以测试的具体依赖关系的东西。
有什么想法吗?
Ninject.IContext
(lambda 中的参数)引用了 IKernel
,因此更改为:
Bind<IQueue>().ToMethod(context => QueueFactory.CreatQueue(context.Kernel.Get<IAdvancedBus>())).InSingletonScope();