Binding one class to several interfaces as singleton
Asked Answered
T

4

18

I have for instance 2 interfases IInterface1 and IInterface2,

public interface IInterface1 {...}
public interface IInterface2 {...} 

and one implementation of these interfaces ImplClass.

public class ImplClass : IInterface1, IInterface2 {...}

I have to be sure that application has only one instance of ImplClass, which will be used as IInterface1 and IInterface2. I'm using ninject for dependency injection. So my qustion is: Does code below will meet my requirements?

...
Bind<IInterface1>().To<ImplClass>().Using<SingletonBehavior>();
Bind<IInterface2>().To<ImplClass>().Using<SingletonBehavior>();
...

Or this code will create 2 instances of ImplClass, for eash interface?

Turfy answered 16/11, 2010 at 14:53 Comment(2)
Duplicate of #3148496Kronfeld
@Kronfeld can you actually vote to close (good call BTW)Source
P
20

With Ninject you can do this:

var impl = new Impl();
container.Bind<IInt1>().ToMethod(c => impl);
container.Bind<IInt2>().ToMethod(c => impl);

When the Impl class has dependencies you can't Ninject to inject, you can do this:

container.Bind<Impl>().ToSelf().InSingletonScope();
container.Bind<IInt1>().ToMethod(c => c.Kernel.Get<Impl>());
container.Bind<IInt2>().ToMethod(c => c.Kernel.Get<Impl>()); 

Nice and clean.

Pestilent answered 16/11, 2010 at 15:3 Comment(4)
I like it. You don't have to set up the class as an actual singleton, but you guarantee only one instance is ever provided.Kbp
-1 Not a good general solution as each resolution leads to an Activation, see #3043941Source
(Better answer until this duplicate question goes away is #10206549 )Source
See Daan's answer below - Ninject v3 now gives you a more elegant way to do this :)Hadfield
I
5

It seems that you're still using Ninject 1.5. I havn't the exact syntax in mind anymore but it should be similat to the following 2.1 syntax:

kernel.Bind<I1>().ToMethod(ctx => ctx.Kernel.Get<Impl>());
kernel.Bind<I2>().ToMethod(ctx => ctx.Kernel.Get<Impl>()); 
kernel.Bind<Impl>().ToSelf().InSingletonScope();

Or even better use Ninject.Extensions.ContextPreservation to keep the context.

kernel.Bind<Impl>().ToSelf().InSingletonScope();
kernel.BindInterfaceToBinding<I1, Impl>();
kernel.BindInterfaceToBinding<I2, Impl>();
Impost answered 17/11, 2010 at 1:42 Comment(2)
@JeffWalkerCodeRanger Please explainImpost
Had upvoted, would like to change to downvote on basis its a duplicate of https://mcmap.net/q/675198/-binding-one-class-to-several-interfaces-as-singleton (and ha the same multiple activation issues)Source
S
3

This is how you can do it in one line of code:

Bind<IInterface1 ,IInterface2 ,ImplClass>().To<ImplClass>().InSingletonScope();

https://github.com/ninject/Ninject.Extensions.ContextPreservation/wiki/BindInterfaceToBinding

It requires Ninject version 3.

Subjoin answered 24/3, 2015 at 18:27 Comment(0)
E
1

I would suspect this would create two instances.

Try whether the following construct works for you:

public class ImplClass : IInterface1, IInterface2
{
    public static readonly ImplClass Instance = new ImplClass();
}

With the following binding:

Bind<IInterface1>().ToMethod(c => ImplClass.Instance);
Bind<IInterface2>().ToMethod(c => ImplClass.Instance);
Elstan answered 16/11, 2010 at 15:2 Comment(1)
Good answer, and a +1, but IMO part of the advantage of an IoC framework is that you can set up a singleton object without having to actually define the class structure as a singleton (making it easier to change your mind later, or set up a container or factory-scoped registration in a different environment). What if he simply initialized a class in the Binding class and registered it as a single-instance scope? (I don't know Ninject's capabilities that well, but Autofac would have no problem doing that).Kbp

© 2022 - 2024 — McMap. All rights reserved.