5

使用 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 : Error activation int 没有匹配的绑定可用,并且类型不是自绑定的。激活路径:
3) 将依赖 int 注入 Bar 类型的构造函数的参数 foo
2) 将依赖 IBar 注入 BarContainer 类型的构造函数的参数 bar
1) 请求 IBarContainer

有没有办法让工厂弄清楚我想在解决“Bar”依赖项时使用传递的“foo”参数?

4

3 回答 3

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 使用你自己的而不是提供的。

希望有帮助

于 2012-06-27T21:58:56.763 回答
3

从 Ninject.Extensions.Factory 的 3.2.0 版本开始,本机支持,使用:

Ninject.Extensions.Factory.TypeMatchingArgumentInheritanceInstanceProvider

你可以像这样使用它:

kernel.Bind<IxxxFactory>()
   .ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());

如果您查看源代码,它是基于先前的答案

于 2015-08-14T08:43:10.680 回答
1

如果我正确理解您的问题,我相信这篇 Ninject Wiki 文章有一个很好的示例(工厂接口),说明如何使用新的 .ToFactory() 绑定扩展,以及如何让这些生成的工厂甚至创建构造函数的对象有参数。

于 2012-10-26T14:09:32.883 回答