C# 构造函数参数。在Kernel.Get工作的地方注入中断

C# 构造函数参数。在Kernel.Get工作的地方注入中断,c#,ninject,C#,Ninject,鉴于以下类别: interface IFoo { } class Foo : IFoo { } class Bar { public Bar(IFoo foo) { } } 以及约束力: Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<Foo>())); 但是,如果我将绑定更改为: Bind<Bar>().ToMethod(ctx => new Bar(ctx.Kernel.G

鉴于以下类别:

interface IFoo { }

class Foo : IFoo { }

class Bar
{
    public Bar(IFoo foo) { }
}
以及约束力:

Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<Foo>()));
但是,如果我将绑定更改为:

Bind<Bar>().ToMethod(ctx => new Bar(ctx.Kernel.Get<Foo>()));
Bind().ToMethod(ctx=>newbar(ctx.Kernel.Get());
我可以按预期获得
Bar
的实例

为什么我会得到那个例外?我的印象是这两个绑定几乎相同,在这两种情况下,
IFoo
的实例从未激活


(非)可在此处看到工作小提琴:

ninject不支持此功能。
ctx.Inject
中指定的类型必须与构造函数参数的类型完全匹配。Ninject从未实际执行您的
新条(…)
,它只分析表达式以确定使用哪个构造函数以及如何注入值

有两种方法可以调整代码以使其正常工作:

  • 更改
    Bar
    的构造函数以接收
    IFoo的
    Foo
    intead
  • Bar的
    ToConstructor
    绑定更改为具有
    ctx.Inject()
    匹配
    Bar的构造函数(
    ctx.Inject()
    ),并为
    IFoo
    创建绑定:

另见:

但是,如果您参考的是关于
T
at
Inject
的类型必须完全匹配的文档:答案同样是否定的。我找不到关于它的任何文档。然而,由于它是开源的,我们可以再次求助于查看实现。同样,可以在中找到,其中包含:

protected IBindingWhenInNamedWithOrOnSyntax<TImplementation> InternalToConstructor<TImplementation>(
    Expression<Func<IConstructorArgumentSyntax, TImplementation>> newExpression)
{
    var ctorExpression = newExpression.Body as NewExpression;
    if (ctorExpression == null)
    {
        throw new ArgumentException("The expression must be a constructor call.", "newExpression");
    }

    this.BindingConfiguration.ProviderCallback = StandardProvider.GetCreationCallback(ctorExpression.Type, ctorExpression.Constructor);
    this.BindingConfiguration.Target = BindingTarget.Type;
    this.AddConstructorArguments(ctorExpression, newExpression.Parameters[0]);

    return new BindingConfigurationBuilder<TImplementation>(this.BindingConfiguration, this.ServiceNames, this.Kernel);
}
使用语法内部构造函数命名时受保护的IBinding(
表达式(新表达式)
{
var=newExpression.Body作为newExpression;
if(表达式==null)
{
抛出新ArgumentException(“表达式必须是构造函数调用。”,“newExpression”);
}
this.BindingConfiguration.ProviderCallback=StandardProvider.GetCreationCallback(ctorExpression.Type,ctorExpression.Constructor);
this.BindingConfiguration.Target=BindingTarget.Type;
this.AddConstructorArguments(ctorExpression,newExpression.Parameters[0]);
返回新的BindingConfigurationBuilder(this.BindingConfiguration、this.ServiceNames、this.Kernel);
}
你可以从这里开始,看看
AddConstructorArguments
以及这些东西是如何工作的,最终你会发现它为什么会这样做;-)
(我不打算为您这样做)

您能指向支持此声明的文档页面吗?我已经更新了答案,以涵盖您关于文档的问题。长话短说:这没有明确记录。
Bind<IFoo>().To<Foo>();
Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<IFoo>()));
public T1 Inject<T1>()
{
    throw new InvalidOperationException("This method is for declaration that a parameter shall be injected only! Never call it directly.");
}
protected IBindingWhenInNamedWithOrOnSyntax<TImplementation> InternalToConstructor<TImplementation>(
    Expression<Func<IConstructorArgumentSyntax, TImplementation>> newExpression)
{
    var ctorExpression = newExpression.Body as NewExpression;
    if (ctorExpression == null)
    {
        throw new ArgumentException("The expression must be a constructor call.", "newExpression");
    }

    this.BindingConfiguration.ProviderCallback = StandardProvider.GetCreationCallback(ctorExpression.Type, ctorExpression.Constructor);
    this.BindingConfiguration.Target = BindingTarget.Type;
    this.AddConstructorArguments(ctorExpression, newExpression.Parameters[0]);

    return new BindingConfigurationBuilder<TImplementation>(this.BindingConfiguration, this.ServiceNames, this.Kernel);
}