如何使用 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
方法将在插入参数的同时解决任何依赖关系。
但是,需要注意的是参数名称必须相同。
我的 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
方法将在插入参数的同时解决任何依赖关系。
但是,需要注意的是参数名称必须相同。