Binding a singleton instance to multiple services (Ninject 2)

3,223 views
Skip to first unread message

Casey

unread,
Aug 6, 2009, 10:57:17 AM8/6/09
to ninject
Forgive me if this question has been asked previously, I was unable to
find anything that seemed to quite fit (and frankly I was not quite
sure how to phrase the question).

My situation is this; I have a concrete class which implements two
interfaces, and I would like to register a binding to this class for
both interface definitions. The trick is that I would like it to be a
singleton, so no matter which interface you asked for, you would get
the same instance of the underlying object. I could probably do
something like create my first binding as a singleton, and then make
the second a method binding that defined a lambda that requested the
object from the kernel using the first service, but this seems really
ugly to me (not to mention not something that can be easily set up
using an automated, discovery).

Here would be a simplified version of what I would like to do:

public class MyClass : IInterface1, IInterface2
{
// .. implementation
}

In bindings:

Bind<IInterface1>().To<MyClass>().InSingletonScope();
Bind<IInterface2>().To<MyClass>().InSingletonScope();

Now when I go to resolve the interfaces:

var myInterface1 = Kernel.Get<IInterface1>(); // Should be the
singleton instance
var myInterface2 = Kernel.Get<IInterface2>(); // Should be the same
object as myInterface1

Assert.That(myInterface2, Is.SameAs(myInterface1)); // This fails, but
I don't want it to.

Does this make sense?

Josh Close

unread,
Aug 6, 2009, 11:16:15 AM8/6/09
to nin...@googlegroups.com
I have had the need to have multiple bindings that create the same object type and wanted them to be in singleton scope also, and 2 singletons are created instead of one.

It would be nice to be able to do that, but I don't know of a way. I found a workaround by restructuring my classes.

I'm interesting in knowing if there is a way I don't know about to do this also.

Josh

Ian Davis

unread,
Aug 6, 2009, 4:53:55 PM8/6/09
to nin...@googlegroups.com
Bind the second to a function and return the request for the first interface.

Please forgive syntax errors

Bind<IInterface1>().To<MyClass>().InSingletonScope();
 Bind<IInterface2>().ToMethod>(context=> context.kernel.Get<MyClass>());

-Ian
--
Ian Davis

Ian Davis

unread,
Aug 6, 2009, 4:54:59 PM8/6/09
to nin...@googlegroups.com
Sorry,

 Bind<IInterface2>().ToMethod>(context=> context.kernel.Get<IInterface1>() as IInterface2);

It is ugly, but it works.
--
Ian Davis

Josh Close

unread,
Aug 6, 2009, 5:03:06 PM8/6/09
to nin...@googlegroups.com
Nice. Ugly, but simple. And if it works well, who cares?

David

unread,
Aug 8, 2009, 2:01:11 PM8/8/09
to ninject
It also creates a tight coupling between those two interfaces. If you
had two cross cutting concern interfaces (like, IStartable and
IInitializable) which are not aware of each other, doesn't that create
a problem?

I think what is really needed is the ability to state that the
instance created for a singleton is global across interfaces. I'm not
sure how to do that, but it less 'ugly' than having the interfaces
being aware of each other, especially since they may not always be
used together.

David

On Aug 6, 5:03 pm, Josh Close <nar...@gmail.com> wrote:
> Nice. Ugly, but simple. And if it works well, who cares?
>
> On Thu, Aug 6, 2009 at 3:54 PM, Ian Davis <ian.f.da...@gmail.com> wrote:
> > Sorry,
>
> >  Bind<IInterface2>().ToMethod>(context=> context.kernel.Get<IInterface1>()
> > as IInterface2);
>
> > It is ugly, but it works.
>
> > On Thu, Aug 6, 2009 at 1:53 PM, Ian Davis <ian.f.da...@gmail.com> wrote:
>
> >> Bind the second to a function and return the request for the first
> >> interface.
> >> Please forgive syntax errors
>
> >>  Bind<IInterface1>().To<MyClass>().InSingletonScope();
> >>  Bind<IInterface2>().ToMethod>(context=> context.kernel.Get<MyClass>());
>
> >> -Ian
>

Ian.F...@gmail.com

unread,
Aug 8, 2009, 4:38:11 PM8/8/09
to ninject
The interfaces are not aware of one another, the binding module is aware that the the object bound to one interface also implements and should be returned to requests by a
second interface.


On Aug 8, 2009 11:01am, David <david.b...@gmail.com> wrote:
>
>
> It also creates a tight coupling between those two interfaces. If you
>
> had two cross cutting concern interfaces (like, IStartable and
>
> IInitializable) which are not aware of each other, doesn't that create
>
> a problem?
>
>
>
> I think what is really needed is the ability to state that the
>
> instance created for a singleton is global across interfaces. I'm not
>
> sure how to do that, but it less 'ugly' than having the interfaces
>
> being aware of each other, especially since they may not always be
>
> used together.
>
>
>
> David
>
>
>
> On Aug 6, 5:03 pm, Josh Close nar...@gmail.com> wrote:
>
> > Nice. Ugly, but simple. And if it works well, who cares?
>
> >
>
> > On Thu, Aug 6, 2009 at 3:54 PM, Ian Davis ian.f.da...@gmail.com> wrote:
>
> > > Sorry,
>
> >
>
> > >  Bind().ToMethod>(context=> context.kernel.Get()
>
> > > as IInterface2);
>
> >
>
> > > It is ugly, but it works.
>
> >
>
> > > On Thu, Aug 6, 2009 at 1:53 PM, Ian Davis ian.f.da...@gmail.com> wrote:
>
> >
>
> > >> Bind the second to a function and return the request for the first
>
> > >> interface.
>
> > >> Please forgive syntax errors
>
> >
>
> > >>  Bind().To().InSingletonScope();
>
> > >>  Bind().ToMethod>(context=> context.kernel.Get());
>
> >
>
> > >> -Ian
>
> >
>
> > >> On Thu, Aug 6, 2009 at 7:57 AM, Casey casey.kra...@gmail.com> wrote:
>
> >
>
> > >>> Forgive me if this question has been asked previously, I was unable to
>
> > >>> find anything that seemed to quite fit (and frankly I was not quite
>
> > >>> sure how to phrase the question).
>
> >
>
> > >>> My situation is this; I have a concrete class which implements two
>
> > >>> interfaces, and I would like to register a binding to this class for
>
> > >>> both interface definitions.  The trick is that I would like it to be a
>
> > >>> singleton, so no matter which interface you asked for, you would get
>
> > >>> the same instance of the underlying object.  I could probably do
>
> > >>> something like create my first binding as a singleton, and then make
>
> > >>> the second a method binding that defined a lambda that requested the
>
> > >>> object from the kernel using the first service, but this seems really
>
> > >>> ugly to me (not to mention not something that can be easily set up
>
> > >>> using an automated, discovery).
>
> >
>
> > >>> Here would be a simplified version of what I would like to do:
>
> >
>
> > >>> public class MyClass : IInterface1, IInterface2
>
> > >>> {
>
> > >>>    // .. implementation
>
> > >>> }
>
> >
>
> > >>> In bindings:
>
> >
>
> > >>> Bind().To().InSingletonScope();
>
> > >>> Bind().To().InSingletonScope();
>
> >
>
> > >>> Now when I go to resolve the interfaces:
>
> >
>
> > >>> var myInterface1 = Kernel.Get();  // Should be the
>
> > >>> singleton instance
>
> > >>> var myInterface2 = Kernel.Get();  // Should be the same

David

unread,
Aug 9, 2009, 10:42:50 PM8/9/09
to ninject
True. I misspoke (mistyped). The interfaces are not aware of each
other, but the specific binding for each interface is. In other words,
I need to have a single module that does the binding for both
interfaces. More importantly the bindings for each interface have to
be aware of each other, as one is defined in terms of the other. This
does not allow me to grow the number of services shared or exposed
with modifying the shared bindings.

Preferably, it would be nice to tell the kernel that a set of global
service interfaces should be bound to singletons if found, and
whenever a singleton instance is bound, it would check for those
interfaces, and autobind.

However, this model does work and solve the functional need. At this
point, I am just trying to find a solution that is more generalized.

Thanks
David

On Aug 8, 4:38 pm, Ian.F.Da...@gmail.com wrote:
> The interfaces are not aware of one another, the binding module is aware  
> that the the object bound to one interface also implements and should be  
> returned to requests by a
> second interface.
>

Sam

unread,
Aug 12, 2009, 4:02:49 PM8/12/09
to ninject
Hi Ian,
I'm having trouble instantiating a Form that implements multiple view
interfaces. I set it up so that my Form has a property-injected
presenter for each view that it implements. The presenter has a
constructor-injected view interface.

When my Form only implemented one view interface, everything was
correctly created. Code:

// binding and app start
kernel.Bind<IMainView>().To<MainForm>().InSingletonScope();
this.MainForm = kernel.Get<IMainView>() as Form;

// presenter
public class MainViewPresenter
{
private IMainView view;

public MainViewPresenter(IMainView view)
{
this.view = view;
}
}

// form
public class MainForm: Form, IMainView
{
private MainViewPresenter presenter;

[Inject]
public MainViewPresenter
{
set
{
this.presenter = value;
}
}
}

This works fine. The kernel builds a MainForm, and then property-
injects a presenter. Because IMainView was bound to MainForm as a
singleton, the presenter's constructor dependency on IMainView can be
resolved.

If MainForm implements multiple views, I get a cyclical dependency
ActivationException.

kernel.Bind<MainForm>().ToSelf.InSingletonScope();
kernel.Bind<IStatisticsView>().ToMethod(context =>
context.Kernel.Get<MainForm>());

this.MainForm = kernel.Get<MainForm>();

StatisticsViewPresenter has a constructor dependency on
IStatisticsView, so Ninject should resolve this by calling the method
kernel.Get<MainForm>(). Because MainForm is bound as a singleton and
because it doesn't need a StatisticsViewPresenter until *after* the
MainForm has been created (since it's property injected), it should
return the current instance of MainForm. But it appears to try to
build a new instance of MainForm; it seems like Ninject doesn't
consider an object instantiated until its properties have been
injected--else, why would context.Kernel.Get<MainForm>() not give me
the already-created (but properties have not yet been injected)
instance of MainForm?

Is there a way to resolve this? I could have the presenter manually
inject itself into the view inside the presenter's constructor, but
then I have to remember to inject every time I make a new presenter
class.

Nate Kohari

unread,
Aug 12, 2009, 4:11:16 PM8/12/09
to nin...@googlegroups.com
Sam:

Actually, I think this is a bug in Ninject2. I ran into it myself, but I haven't had a chance to find the root cause yet. I'll look into it.


Thanks,
Nate

Micha

unread,
Aug 13, 2009, 3:12:57 AM8/13/09
to ninject
Hi Sam,
I think the IoC Tool shouldn't be (mis)used to manage your views.
Checking for an existing view e.g. shouldn't be done by SingletonScope
but by some kind of view manager. Also consider implementing your view
interfaces in separate forms or controls and just show them within
your MainForm. (Separation of Concerns, Single Responsibility and
Interface Segregation Principle)

An excellent reference for how to handle views, presenters etc. is
http://www.jeremydmiller.com/ppatterns or his Build Your Own CAB
series!

Micha.

Aaron Lerch

unread,
Sep 25, 2009, 3:27:10 PM9/25/09
to ninject
Nate, do you have any comments about the nature of the original
request? Binding multiple interfaces to a singleton scoped class?

Miguel Madero

unread,
Sep 25, 2009, 10:14:08 PM9/25/09
to nin...@googlegroups.com
You could use a constant instead, the only drawback I can think of would be that you need to eagerly initialize it.
--
Miguel A. Madero Reyes
www.miguelmadero.com (blog)
m...@miguelmadero.com

Aaron Lerch

unread,
Sep 25, 2009, 10:45:06 PM9/25/09
to ninject
I can't use a constant if it depends on other bindings that may or may
not have been registered yet (the app is loosely coupled and not all
dependencies are guaranteed to be loaded at the moment of binding).
I was able to refactor around the problem, but it's not a clean
solution (it'll do for now, and it's better than type-casting within a
binding). I had to add a layer of indirection (for no reason :)).
I actually started spiking implementing this in Ninject itself, if I
have time I'll try to see how it could work (if nothing else, to
provide feedback to the devs)

Miguel Madero

unread,
Sep 26, 2009, 11:01:17 PM9/26/09
to nin...@googlegroups.com
I understand, you're right. Just another idea, although I'm not sure its appropriate for your scenario.

You could register one singleton and some Callbacks for the other interfaces. For example:

public class MyClass : IInterface, IMyOtherInterface, IYetAnotherInterface{}

Bind<MyClass>().ToSelf().InSingletonScope();
            Bind<IInterface>().ToMethod(x => x.Kernel.Get<MyClass>());
            Bind<IMyOtherInterface>().ToMethod(x => x.Kernel.Get<MyClass>());
            Bind<IYetAnotherInterface>().ToMethod(x => x.Kernel.Get<MyClass>());

Sam

unread,
Sep 29, 2009, 3:35:33 PM9/29/09
to ninject
Hi Micha,
Essentially what I am trying to accomplish is a version of
StructureMap's BuildUp method, which populates properties with
existing instances, or new instances if they do not exist. That way I
can have my views' presenters automatically injected into my views
rather than manually calling some view.AttachPresenter(presenter)
method on the view. Is there any other way to do this other than
using InSingletonScope()?
> An excellent reference for how to handle views, presenters etc. ishttp://www.jeremydmiller.com/ppatternsor his Build Your Own CAB
> series!
>
> Micha.
Reply all
Reply to author
Forward
0 new messages