我的班级结构是:
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是从服务中获取的,在编译时不可用。
如果需要任何其他信息,请随时发表评论。
答案 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
。