In other DI containers, I have observed TryAddScoped, TryAddTransient, TryAddSingleton etc.
The idea behind Try is to avoid registering multiple times. If a service is already registered, then using Try will not attempt to register again I guess.
With inject
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
So is there any Try equivalent in Ninject?
There's no simple equivalent.
Performing
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
will result in in an exception when resolving a IHttpContextAccessor
, and when resolving IEnumerable<IHttpContextAccessor>
it will return two HttpContextAccessor
instances.
However, you can write your own "Try":
if(!Kernel.GetBindings(typeof(IHttpContextAccessor)).Any())
{
Kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
}
Of course you can also write your own extension method for that:
public static class NinjectBindingExtensions
{
public static void TryBind<T>(
this IKernel kernel,
Action<IBindingToSyntax<T>> configureBinding)
{
if (!kernel.GetBindings(typeof(T)).Any())
{
configureBinding(kernel.Bind<T>());
}
}
}
One way to work around the issue is to use .Rebind
instead of .Bind
. If there's no pre-existing binding it will work just like .Bind
. And if there's a pre-existing binding, it will replace it. Thus:
Kernel.Rebind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Kernel.Rebind<IHttpContextAccessor>().To<HttpContextAccessor>().InSingletonScope();
Resolving IHttpContextAccessor
will result in one instance of HttpContextAccessor
.
In case the problem is not with multiple components / NinjectModule
s creating bindings for the same type, but rather with loading the same NinjectModule
twice, you can can prevent duplicate loading by:
if(!Kernel.HasModule(typeof(MyModule)))
{
Kernel.Load<MyModule>();
}