使用Ninject Factory扩展,您可以自动生成工厂,并让工厂将参数传递给类的构造函数。以下测试通过:
public interface IBar
{
int Foo { get; }
}
public class Bar : IBar
{
int _foo;
public Bar(int foo) { _foo = foo; }
public int Foo { get { return _foo; } }
}
public interface IBarFactory
{
IBar CreateTest(int foo);
}
[Test]
public void ExecuteTest()
{
var kernel = new StandardKernel();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IBarFactory>().ToFactory();
var factory = kernel.Get<IBarFactory>();
var actual = factory.CreateTest(42);
Assert.That(actual, Is.InstanceOf<Bar>());
}
但是,在我的特定问题中,我希望它将工厂参数传递给我正在构建的类的依赖项,而不是类本身,如下所示:
public interface IBarContainer
{
IBar Bar { get; }
}
public class BarContainer : IBarContainer
{
IBar _bar;
public BarContainer(IBar bar) { _bar = bar; }
public IBar Bar { get { return _bar; } }
}
public interface ITestContainerFactory
{
IBarContainer CreateTestContainer(int foo);
}
[Test]
public void ExecuteTestContainer()
{
var kernel = new StandardKernel();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IBarContainer>().To<BarContainer>();
kernel.Bind<ITestContainerFactory>().ToFactory();
var factory = kernel.Get<ITestContainerFactory>();
var actual = factory.CreateTestContainer(42);
Assert.That(actual.Bar, Is.InstanceOf<Bar>());
}
此测试失败并显示以下消息:
Ninject.ActivationException:激活int时出错无匹配 绑定可用,并且类型不可自绑定。激活 路径:
3)将依赖项int注入到类型为Bar的构造函数的参数foo中 2)将依赖关系IBar注入到BarContainer型构造函数的参数栏中 1)申请IBarContainer
有没有办法让工厂弄清楚我想在解析'Bar'依赖时使用传递的'foo'参数?
答案 0 :(得分:4)
HY, 默认实例提供程序不使用继承的构造函数参数。您可以通过编写自己的实例提供程序来更改此行为,如下所示:
public class CustomInstanceProvider : StandardInstanceProvider {
protected override ConstructorArgument[]
GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
var parameters = methodInfo.GetParameters();
var constructorArguments =
new ConstructorArgument[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
constructorArguments[i] =
new ConstructorArgument
(parameters[i].Name, arguments[i], true);
}
return constructorArguments;
}
}
然后你只需要指示ninject使用你自己的而不是提供的。
希望有所帮助
答案 1 :(得分:3)
从Ninject.Extensions.Factory版本3.2.0开始,本机支持使用:
Ninject.Extensions.Factory.TypeMatchingArgumentInheritanceInstanceProvider
你可以像这样使用它:
kernel.Bind<IxxxFactory>()
.ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());
如果查看source code,则会基于previous answer。
答案 2 :(得分:1)
如果我正确理解你的问题,我相信这篇Ninject Wiki文章有一个很好的例子(Factory interface),关于如何使用新的.ToFactory()绑定扩展,以及如何获得那些生成的工厂甚至创建构造函数具有参数的对象。