我可以使用Ninject实例化不依赖于任何东西的单例服务吗?
本文关键字:单例 服务 任何东 依赖于 可以使 Ninject 实例化 我可以 | 更新日期: 2023-09-27 18:02:52
我的asp.net mvc应用程序中有一些服务侦听AMQP消息并调用方法。
没有控制器依赖于它,所以它不会被自己实例化。
我可以手动实例化它,显式地提供它与kernel.Get
的依赖关系,但感觉我不应该这样做。
我可以使Ninject在单例作用域急切地实例化类,即使没有其他依赖于它?
你不能有ninject实例化的东西,以防你不要求它实例化自己的东西。简单的方法是让ninject实例化组合根目录下的东西:
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies()); // loads all modules in assemlby
//...
// resolution root completely configured
kernel.Resolve<IFooSingleton>();
kernel.Resolve<IBarSIngleton>();
实际上有一种替代方法,虽然不一样,但可以达到类似的效果。它要求至少有一个其他服务很快实例化:Ninject.Extensions.DependencyCreation。它是这样工作的:
kernel.Bind<string>().ToConstant("hello");
kernel.Bind<ISingletonDependency>().To<SingletonDependency>()
.InSingletonScope();
kernel.DefineDependency<string, ISingletonDependency>();
kernel.Get<string>();
// when asking for a string for the first time
// ISingletonDependency will be instantiated.
// of course you can use any other type instead of string
Ninject不像其他容器(例如Autofac),它不是分阶段"构建"的。没有先创建绑定,然后再创建内核来使用它们的概念。以下是完全合法的:
kernel.Bind<IFoo>()...
kernel.Get<IFoo>()...
kernel.Bind<IBar>()...
kernel.Get<IBar>()...
so ninject不可能知道当你想要实例化的单例。使用autoface,它是清晰和容易的:
var containerBuilder = new ContainerBuilder();
containerBuilder
.RegisterType<Foo>()
.AutoActivate();
var container = containerBuilder.Build(); // now
来自Java的Guice,我非常怀念急切单例模式。它们在模块充当插件的场景中非常有用。如果您想象一个服务是由配置中指定的模块组装而成的,那么您可能会发现一个问题,即当应用程序启动时,还试图指定该模块需要自动实例化的内容。
对我来说,模块是定义应用程序组合的地方,将渴望的单例分离到代码中的另一个地方感觉更笨拙,更不直观。
无论如何,我已经能够很容易地实现这个图层在Ninject之上,下面是代码:
public static class EagerSingleton
{
public static IBindingNamedWithOrOnSyntax<T> AsEagerSingleton<T>(this IBindingInSyntax<T> binding)
{
var r = binding.InSingletonScope();
binding.Kernel.Bind<IEagerSingleton>().To<EagerSingleton<T>>().InSingletonScope();
return r;
}
}
public interface IEagerSingleton { }
public class EagerSingleton<TComponent> : IEagerSingleton
{
public EagerSingleton(TComponent component)
{
// do nothing. DI created the component for this constructor.
}
}
public class EagerSingletonSvc
{
public EagerSingletonSvc(IEagerSingleton[] singletons)
{
// do nothing. DI created all the singletons for this constructor.
}
}
创建内核之后,添加一行:
kernel.Get<EagerSingletonSvc>(); // activate all eager singletons
你可以这样在模块中使用它:
Bind<UnhandledExceptionHandlerSvc>().ToSelf().AsEagerSingleton();