使用Ninject在特定的对象子树中进行不同的绑定
本文关键字:绑定 Ninject 对象 使用 | 更新日期: 2023-09-27 18:15:09
我正在使用Ninject在我的项目中执行依赖注入,我遇到了一个问题。我需要在"对象树"的特定子树的绑定中指定一个异常(意思是包含而不是继承)。假设我们有几个接口和类(我已经排除了构造函数和其他无关的东西):
interface Wheel { ... }
class RoundWheel : Wheel { ... }
class SquareWheel : Wheel { ... }
class Mechanism { Wheel Wheel; ... }
class Bike { Wheel Wheel; ... }
class Items { Mechanism Mechanism; Bike Bike; ... }
我想将Wheel
绑定到SquareWheel
,当它以某种方式包含在Mechanism
中(Mechanism
可以在更高的地方,例如。Item.Mechanism.ContainerForWheel.(any types further on).Wheel
),否则转RoundWheel
。现在,让我们看看我当前的解决方案:
IKernel kernel = new StandardKernel();
kernel.Bind<Wheel>().To<RoundWheel>();
kernel.Bind<Wheel>().To<SquareWheel>().When(x => x.ActiveBindings.Any(p => p.Service.Name == typeof(Mechanism).Name));
Items items = kernel.Get<Items>();
它像一个魅力,但看起来非常不优雅和次优。很难理解这种过滤的明确目的。你知道其他的方法吗?提前谢谢。
编辑1 我忘了说,我不想把任何注解和其他东西放到我的类中。
我认为没有比这更简单的方法了。您还可以显式遍历IContext.ParentRequest
并检查是否存在特定的Mechanism
。这将比使用ActiveBindings
属性更显式一些。但是既不会更快,也不会导致更少的代码。
但是你可以做的是应用干净的代码并创建你自己的When-Extension,所以你最终会得到:
kernel.Bind<Wheel>().To<SquareWheel>()
.When(IsDescendantOf<Mechanism1>);
private static bool IsDescendantOf<T>(IRequest request)
{
return request.ActiveBindings.Any(p => p.Service.Name == typeof(T).Name);
}
或者,使用扩展方法:
kernel.Bind<IWheel>().To<Wheel2>()
.WhenIsDescendantOf(typeof(Mechanism1));
public static class NinjectWhenExtensions
{
public static IBindingInNamedWithOrOnSyntax<T> WhenIsDescendantOf<T>(this IBindingWhenSyntax<T> syntax, Type ancestor)
{
return syntax.When(request => request.ActiveBindings.Any(p => p.Service.Name == ancestor.Name));
}
}
顺便说一句。,您还应该能够用p.Service == typeof(Mechanism)
替换检查p.Service.Name == typeof(Mechanism).Name
。当名称匹配时,类型也应该匹配。但是,如果您使用的是接口,则必须调整逻辑。