【发布时间】:2012-06-06 20:38:32
【问题描述】:
我有一个大致如下所示的依赖链:
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 { ... }
到目前为止,我一直在使用基于约定的绑定,但这还不够好,因为我已经为 IFtpSettings 提供了多个实现。所以我决定使用一些上下文绑定。乍一看,kernel.Bind<>().To<>().WhenInjectedInto<>() 看起来很有希望,但这只会在第一级有所帮助,这意味着如果我有一个 CarSalesFtpFileProvider 和一个 MotorcycleSalesFtpProvider 我可以这样做:
kernel.Bind<IFtpSettings>().To<CarSalesFtpSettings>()
.WhenInjectedInto<CarSalesFtpFileProvider>();
kernel.Bind<IFtpSettings>().To<MotorcycleSalesFtpSettings>()
.WhenInjectedInto<MotorcycleSalesFtpFileProvider>();
但是创建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);
}
因此,如果构造函数请求 IFtpSettings,我们会递归请求树以查看链中是否有任何请求的服务/类型与提供的类型(CarSalesBatchJob 或 MotorcycleSalesBatchJob)匹配,如果匹配则返回 true。如果我们一直到达链的顶部,则返回 false。
抱歉,背景解释太长了。
这是我的问题:我有什么理由不应该以这种方式解决问题?这被认为是不好的形式吗?有没有更好的方法来查找祖先请求类型?我应该将我的类/依赖链重组为更“合意”的方式吗?
【问题讨论】:
-
我相信您在问题中确定的解决方案是实现两个将 FtpFileProvider 与 IFtpSettings 实现配对的具体类,是最容易理解/读取/调试/移交的解决方案。其他解决方案要求开发人员更多地了解您的特定 IOC 工具以及您如何配置它。此实现还遵循 Ninject 的约定优于配置。
标签: .net dependency-injection inversion-of-control ninject