如何在Ninject中将相同的依赖项绑定到许多依赖项?

时间:2012-09-12 02:57:35

标签: c# dependency-injection ninject

我们有三个界面:IFooIBarIBaz。我还有各自的实现类FooBarBaz

在实现中,每个都取决于接口IContainer。因此对于Foo(以及BarBaz的类似情况),实现可能会显示为:

class Foo : IFoo
{
    private readonly IDependency Dependency;

    public Foo(IDependency dependency)
    {
           Dependency = dependency;
    }

    public void Execute()
    {
         Console.WriteLine("I'm using {0}", Dependency.Name);
    }
}

让我们进一步说我有一个类Container恰好包含IFooIBarIBaz的实例:

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;
    }
}

在这种情况下,我希望实现类ContainerIContainer绑定,其约束条件是IDependency被注入IFooIBar },IBaz对所有三个都是一样的。以手动方式,我可以将其实现为:

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);

我如何在Ninject中实现这一目标?

注意:我不是在询问如何进行嵌套依赖。我的问题是如何保证物化服务中对象集合中给定的依赖关系是相同的。

为了非常明确,我理解Ninject在其标准格式中将生成与以下内容等效的代码:

IContainer container = new Container(new Foo(new Dependency()), new Bar(new Dependency()), new Baz(new Dependency()));

喜欢这种行为。我不能将Dependency创建为单身人士。具体来说,这意味着如果我有多个GetService<IContainer>请求,Ninject调用应该在语义上等同于以下手动注入:

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));

3 个答案:

答案 0 :(得分:3)

使用ToConstant方法指定要绑定的确切实例。如果有机会,您可以使用Unbind重新绑定到另一个实例:

        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...

答案 1 :(得分:1)

编辑:

这个怎么样?

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);
            });

答案 2 :(得分:1)

这是另一次尝试:

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; }
}

然后:

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>();