使用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 我忘了说,我不想把任何注解和其他东西放到我的类中。

使用Ninject在特定的对象子树中进行不同的绑定

我认为没有比这更简单的方法了。您还可以显式遍历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。当名称匹配时,类型也应该匹配。但是,如果您使用的是接口,则必须调整逻辑。