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

时间:2015-02-26 14:43:41

标签: .net c#-4.0 ninject

我的班级结构是:

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

My Ninject Bindings就像:

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是从服务中获取的,在编译时不可用。

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

3 个答案:

答案 0 :(得分:4)

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

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

现在需要注意的是,这只是一个级别。但是有一个构造函数接受一个名为shouldInherit的bool标志,它允许你的值在解析具体类型时传播给子节点:

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

答案 1 :(得分:3)

虽然我发现在某些情况下它有点过分,但使用工厂将有助于提供类似构造函数的功能,同时保留注射的书写风格。这是由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方法将解决与插入参数并行的所有依赖项。

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

答案 2 :(得分:2)

Yannick的答案很好,但是,这里有另一种选择:创建一个IAccountService,它具有查找和返回AccountId的逻辑。然后将该服务注入您的IPhotoService