如何使用 Ninject 在依赖链中传递参数

How to pass parameters down the dependency chain using Ninject

我的 Class 结构是:

public class PhotoService {

    private IRepository _repo;
    private DTConfig _config;

    public PhotoService(IRepository repo, DTConfig config)
    {    

        _repo = repo;
        _config = config;
    }
}

public class DTConfig
{
     private int _accountId;
     public DTConfig(int accountId)
     {
           _accountId = accountId;
     }
}

我的 Ninject 绑定如下:

var kernel = new StandardKernel();
kernel.Bind<IPhotoService>().To<PhotoService>();
kernel.Bind<IRepository>().To<Repository>();
kernel.Bind<DTConfig>().ToSelf();

现在我想要的是在创建 PhotoService

实例时将 accountId 作为参数传递
var photo = kernel.Get<IPhotoService>(); 

如何在创建 PhotoService 实例时将参数传递给 DTConfig。 accountId 是从服务中获取的,在编译时不可用。

如果需要任何其他信息,请随时发表评论。

Ninject 中有一个 ConstructorArgument 的概念,它允许您传递仅在运行时已知的变量。典型的例子是:

var photoService = kernel.Get<IPhotoService>(new ConstructorArgument("accountId", <your value here>));

现在需要注意的是,这只会深入 一个 级别。然而,有一个构造函数接受一个名为 shouldInherit 的布尔标志,它允许您的值在解析具体类型时传播到 children:

var photoService  = kernel.Get<IPhotoService>(new ConstructorArgument("accountId", <your value here>, shouldInherit:true));

Yannick 的回答很好,但是,这里有一个替代方案:创建一个 IAccountService 具有查找逻辑和 return AccountId。然后将该服务注入您的 IPhotoService.

虽然我发现它在某些情况下有点矫枉过正,但使用工厂将有助于提供类似构造函数的功能,同时保留注入的编写风格。这是由 Ninject.Extensions.Factory extension.

提供的

在基本层面上,您创建一个工厂接口,它具有匹配的构造函数参数子集。它既可以解析绑定组件,又需要输入本身。这是 wiki;

中的一个稍作修改的示例
public class Foo
{
    readonly IBarFactory barFactory;

    public Foo(IBarFactory barFactory)
    {
        this.barFactory = barFactory;
    }

    public void Do()
    {
        var bar = this.barFactory.CreateBar("doodad");
        //Do Foo things
        bar.Stuff();
    }
}

public interface IBarFactory
{
    IBar CreateBar(string someParameter);
}
public interface IBar
{
    void Stuff();
}

public class Bar : IBar
{
    public Bar(IDependancy aDependancy, string someParameter)
    {
        //Initialise Object
    }
    public void Stuff()
    {
        //Do Stuff
    }
}

然后通过绑定一个工厂;

_kernel.Bind<IBarFactory>().ToFactory();

该扩展程序会在幕后发挥一些作用。

在此示例中,假设 IDependancy 已正确绑定,调用工厂的 CreateBar 方法将在插入参数的同时解决任何依赖关系。

但是,需要注意的是参数名称必须相同。