ConstructorArgument.Inject 中断了 Kernel.Get 工作的地方
本文关键字:工作 Get Kernel Inject 中断 ConstructorArgument | 更新日期: 2023-09-27 18:24:27
给定以下类:
interface IFoo { }
class Foo : IFoo { }
class Bar
{
public Bar(IFoo foo) { }
}
和绑定:
Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<Foo>()));
调用 kernel.Get<Bar>()
会引发以下异常:
An unhandled exception of type 'Ninject.ActivationException' occurred in Ninject.dll
Additional information: Error activating IFoo
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IFoo into parameter foo of constructor of type Bar
1) Request for Bar
但是,如果我将绑定更改为:
Bind<Bar>().ToMethod(ctx => new Bar(ctx.Kernel.Get<Foo>()));
我可以按预期获得Bar
的实例。
为什么我会收到该异常?我的印象是这两个绑定几乎相同,并且在这两种情况下,IFoo
的实例都不会被激活。
(不是(工作小提琴可以在这里看到:https://dotnetfiddle.net/qmPFhr
ninject不支持这一点。ctx.Inject<>
中指定的类型必须与构造函数参数的类型完全匹配。Ninject 从未实际执行过您的new Bar(...)
,它只分析表达式以确定要使用的构造函数以及如何注入值。
方法可以调整代码以使其正常工作:
- 更改
Bar
的构造函数以接收IFoo
的Foo
。 - 更改
Bar
的ToConstructor
绑定,使其ctx.Inject<>()
与Bar
(ctx.Inject<IFoo>()
( 的构造函数匹配,并为IFoo
创建绑定:
.
Bind<IFoo>().To<Foo>();
Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<IFoo>()));
根据您的文件要求
不,除了源/api之外,它没有记录在任何其他文档中,ctx.Inject<>
实际上从未执行过。但是,从该方法的参数中可以明显看出是Expression<Func<..>>
而不是Func<..>
。如果执行,Func<..>
就足够了。 Expression
在那里,因此您可以分析它们的内容。
另外,在查看BindingBuilder.cs
源时,Inject<T1>
方法实际上只做一件事:抛出异常:
public T1 Inject<T1>()
{
throw new InvalidOperationException("This method is for declaration that a parameter shall be injected only! Never call it directly.");
}
另请参阅:http://ivanitskyi.blogspot.com/2013/06/linq-func-vs-expression.html
但是,如果您指的是有关Inject<T>
T
类型必须完全匹配的文档:答案是否定的。我找不到任何关于它的文档。但是,由于它是开源的,我们可以再次查看实现。同样,它在 BindingBuilder.cs
中找到,其中包含:
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);
}
你可以从那里看看AddConstructorArguments
以及这些东西是如何工作的,最终你会发现为什么它的行为如此;-((我不会为你这样做(