binding to a factory of another bound type

33 views
Skip to first unread message

fschwiet

unread,
Jul 18, 2010, 9:10:17 PM7/18/10
to ninject
I've been playing with Ninject to see if it has the features I need to
port a project over to it. One feature that seemed missing was the
ability to bind to a factory method for a service. You can bind a
service to a factory method, but this is different. What I mean is
that a class can take as a dependency a factory method, where that
factory method can be any service already bound within that kernel.
So the class can create multiple instances of the dependency it has.

For example, a Juggler needs more than 1 weapon, they may need many
weapons over time. In fact every time they pull out a weapon, its a
new one, because presumably the old one was dropped.

public class Juggler : IWarrior
{
private readonly Func<IWeapon> _weaponFactory;

public Juggler(Func<IWeapon> weaponFactory)
{
_weaponFactory = weaponFactory;
}

public IWeapon Weapon
{
get { return _weaponFactory(); }
}
}

I'm not sure Ninject supports this natively, I couldn't find it.
Here's a test case. It passes, with the commit linked below. I'm
just sharing, and wondering if anyone else thinks this is useful or
perhaps has thoughts on a better approach.

class FactoryBindingTests : FactoryBindingContext
{
[Fact]
public void can_bind_factory()
{
kernel.Bind<IWeapon>().To<Sword>();
kernel.Bind<Juggler>().ToSelf();

var result = kernel.Get<Juggler>();

Assert.NotNull(result);
}
}

Commit adding this capability:
http://github.com/fschwiet/ninject/commit/1ae73369725b4378a178c379e2b65011bee68d58

Remo Gloor

unread,
Jul 19, 2010, 6:26:53 AM7/19/10
to ninject
Yes that's possible

public WeaponFactory : IWeaponFactory
{
private readonly IKernel kernel;
public WeaponFactory(IKernel kernel)
{
this.kernel = kernel;
}

public IWeapon CreateWeapon()
{
return this.kernel.Get<IWeapon>();
}
}

public class Juggler : IWarrior
{
private readonly IWeaponFactory _weaponFactory;

public Juggler(IWeaponFactory weaponFactory)
{
_weaponFactory = weaponFactory;
}

public IWeapon Weapon
{
get { return _weaponFactory.CreateWeapon(); }
}
}

fschwiet

unread,
Jul 19, 2010, 12:10:09 PM7/19/10
to ninject
Oh yeah I forgot about that approach. I like to be more explicit
with the dependencies, to have a dependency on IKernel leaves some
question as to what the dependency is for. Requiring a specific
factory was useful when I was generating dependency graphs for the
final result, though I don't have that capability with Ninject yet.

Urs Enzler

unread,
Jul 21, 2010, 4:38:14 AM7/21/10
to ninject
Hei Remo

[InsiderJoke]
Since when do we pass IKernel into a factoy anf not an
IResolutionRoot ;-)
[/InsiderJoke]

There is no reason to pass in the kernel because no additional
bindings are defined. An IResolutionRoot is sufficient and more
flexible.

Cheers,
Urs

Remo Gloor

unread,
Jul 21, 2010, 11:43:41 AM7/21/10
to ninject
Of course IResolutionRoot is preferable. But in that case you have to
define a binding from IResolutionRoot to the kernel because Ninject
has only IKernel by default. Or in case you need to know the parent
context in the factory you can load my ContextPreservationModule which
already has defined this binding.
Reply all
Reply to author
Forward
0 new messages