Reputation: 12817
Let's I have three interfaces: IFoo
, IBar
, IBaz
. I also have the classes Foo
, Bar
, and Baz
that are the respective implementations.
In the implementations, each depends on the interface IContainer
. So for the Foo
(and similarly for Bar
and Baz
) the implementation might read:
class Foo : IFoo
{
private readonly IDependency Dependency;
public Foo(IDependency dependency)
{
Dependency = dependency;
}
public void Execute()
{
Console.WriteLine("I'm using {0}", Dependency.Name);
}
}
Let's furthermore say I have a class Container
which happens to contain instances of the IFoo
, IBar
and IBaz
:
class Container : IContainer
{
private readonly IFoo _Foo;
private readonly IBar _Bar;
private readonly IBaz _Baz;
public Container(IFoo foo, IBar bar, IBaz baz)
{
_Foo = foo;
_Bar = bar;
_Baz = baz;
}
}
In this scenario, I would like the implementation class Container
to bind against IContainer
with the constraint that the IDependency
that gets injected into IFoo
, IBar
, and IBaz
be the same for all three. In the manual way, I might implement it as:
IDependency dependency = new Dependency();
IFoo foo = new Foo(dependency);
IBar bar = new Bar(dependency);
IBaz baz = new Baz(dependency);
IContainer container = new Container(foo, bar, baz);
How can I achieve this within Ninject?
Note: I am not asking how to do nested dependencies. My question is how I can guarantee that a given dependency is the same among a collection of objects within a materialized service.
To be extremely explicit, I understand that Ninject in it's standard form will generate code that is equivalent to the following:
IContainer container = new Container(new Foo(new Dependency()), new Bar(new Dependency()), new Baz(new Dependency()));
I would not like that behavior. I cannot have the Dependency
created as a singleton either. Specifically, this means that if I have multiple requests to GetService<IContainer>
, the Ninject calls should be semantically equivalent to the following manual injection:
var dep1 = new Dependency();
var container1 = new IContainer(new Foo(dep1), new Bar(dep1), new Baz(dep1));
var dep2 = new Dependency();
var container2 = new IContainer(new Foo(dep2), new Bar(dep2), new Baz(dep2));
Upvotes: 4
Views: 220
Reputation: 6401
Here's another attempt:
public class Container : IContainer
{
private IFoo _foo;
private IBar _bar;
private IBaz _baz;
public Container(IContainerDependencies dependencies)
{
_foo = dependencies.Foo;
_bar = dependencies.Bar;
_baz = dependencies.Baz;
}
}
public class ContainerDependencies : IContainerDependencies
{
public ContainerDependencies(IFoo foo, IBar bar, IBaz baz)
{
Foo = foo;
Bar = bar;
Baz = baz;
}
public IFoo Foo { get; set; }
public IBar Bar { get; set; }
public IBaz Baz { get; set; }
}
public interface IContainerDependencies
{
IFoo Foo { get; set; }
IBar Bar { get; set; }
IBaz Baz { get; set; }
}
Then:
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IBaz>().To<Baz>();
kernel.Bind<IContainerDependencies>().ToMethod(context =>
{
context.Kernel.Unbind<IDependency>();
context.Kernel.Bind<IDependency>().ToConstant(new Dep());
return context.Kernel.Get<ContainerDependencies>();
});
kernel.Bind<IContainer>().To<Container>();
Upvotes: 1
Reputation: 18533
Use ToConstant
method to specify exact instance to bind to. If there is an opportunity you can use Unbind
to rebind to another instance:
IKernel nKernel = new StandardKernel();
nKernel.Bind<IFoo>().To<Foo>();
nKernel.Bind<IBar>().To<Bar>();
nKernel.Bind<IBaz>().To<Baz>();
nKernel.Bind<IContainer>().To<Container>();
nKernel.Bind<IDependency>().ToConstant(new Dependency());
Container c = nKernel.Get<Container>();
//utilize the container...
nKernel.Unbind<IDependency>();
nKernel.Bind<IDependency>().ToConstant(new Dependency());
c = nKernel.Get<Container>();
//utilize the container...
Upvotes: 3
Reputation: 6401
EDIT:
How about this?
kernel.Bind<IContainer>().ToMethod(context =>
{
IDependency dependency = new Dep();
IFoo foo = new Foo(dependency);
IBar bar = new Bar(dependency);
IBaz baz = new Baz(dependency);
return new Container(foo, bar, baz);
});
Upvotes: 1