Ninject绑定T型的祖先

vig*_*ity 11 .net dependency-injection ninject inversion-of-control

我有一个看起来大致如下的依赖链:

public class CarSalesBatchJob
{
    public CarSalesBatchJob(IFileProvider fileProvider)
    { ... }
}

public class MotorcycleSalesBatchJob
{
    public MotorcycleSalesBatchJob(IFileProvider fileProvider)
    { ... }
}    

public class FtpFileProvider : IFileProvider
{
    public FtpFileProvider(IFtpSettings settings)
    { ... }
}

public class CarSalesFtpSettings : IFtpSettings { ... }
public class MotorcycleSalesFtpSettings : IFtpSettings { ... }
Run Code Online (Sandbox Code Playgroud)

到目前为止,我一直在使用基于约定的绑定,但这已经不够好了,因为我有多个实现IFtpSettings.所以我决定使用一些上下文绑定.乍一看,kernel.Bind<>().To<>().WhenInjectedInto<>()看起来很有希望,但这只对第一级有帮助,这意味着如果我有一个CarSalesFtpFileProvider和一个MotorcycleSalesFtpProvider我可以做到这一点:

kernel.Bind<IFtpSettings>().To<CarSalesFtpSettings>()
    .WhenInjectedInto<CarSalesFtpFileProvider>();
kernel.Bind<IFtpSettings>().To<MotorcycleSalesFtpSettings>()
    .WhenInjectedInto<MotorcycleSalesFtpFileProvider>();
Run Code Online (Sandbox Code Playgroud)

但是创建两个具体实现似乎非常愚蠢FtpFileProvider,实际上只有我希望它们使用的设置不同.我看到有一个叫做的方法WhenAnyAnchestorNamed(string name).但是这条路线要求我在我的批处理作业中放置属性和魔术字符串,我并不感到兴奋.

我还注意到.When(Func<IRequest, bool>)绑定语句有一个简单的旧方法,所以我想出了这个作为我的绑定语句:

//at this point I've already ran the conventions based bindings code so I need to unbind
kernel.Unbind<IFtpSettings>();
kernel.Bind<IFtpSettings>().To<CarSalesFtpSettings>()
    .When(r => HasAncestorOfType<CarSalesBatchJob>(r));
kernel.Bind<IFtpSettings>().To<MotorcycleSalesFtpSettings>()
    .When(r => HasAncestorOfType<MotorcycleSalesBatchJob>(r));

// later on in the same class
private static bool HasAncestorOfType<T>(IRequest request)
{
    if (request == null)
        return false;

    if (request.Service == typeof(T))
        return true;

    return HasAncestorOfType<T>(request.ParentRequest);
}
Run Code Online (Sandbox Code Playgroud)

因此,如果构造函数请求IFtpSettings,我们会递归请求树以查看链中所请求的任何服务/类型是否与提供的类型(CarSalesBatchJob或MotorcycleSalesBatchJob)匹配,如果是,则返回true.如果我们一直到达链的顶部,我们返回false.

很抱歉有很长的背景说明.

这是我的问题:我有什么理由不这样解决问题吗?这被认为是不好的形式吗?有没有更好的方法来查找祖先请求类型?我应该将我的课程/依赖链重构为更"愉快"的方式吗?

Rem*_*oor 6

您应该使用request.Target.Member.ReflectedType而不是request.Service这是实现类型.

此外,当AnyAncestorNamed不需要属性时.您可以使用该Named方法标记作业的绑定.