我在Ninject模块中重复了几次以下代码。我可以使用哪些方法和技术来减少重复的代码?
public override void Load()
{
Bind<IDataReader<IList<Price>>>()
.To<PricesDataReader>().Named("ValDatePrices");
Bind<IDataConnection<IList<PricesCsvRecord>>>()
.To<PricesXLConnection>().WhenParentNamed("ValDatePrices")
.Named("ValDatePricesXLConnection");
Bind<IDirectoryBuilder>()
.ToMethod(DefaultValDatePricesDirectory)
.WhenParentNamed("ValDatePricesXLConnection");
Bind<IDataReader<IList<Price>>>()
.To<PricesDataReader>().Named("EDDatePrices");
Bind<IDataConnection<IList<PricesCsvRecord>>>()
.To<PricesXLConnection>().WhenParentNamed("EDDatePrices")
.Named("EDDatePricesXLConnection");
Bind<IDirectoryBuilder>()
.ToMethod(DefaultEDDatePricesDirectory)
.WhenParentNamed("EDDatePricesXLConnection");
}
主要区别在于请求IDirectoryBuilder
,其主要功能是通过使用IDirectory
实施来根据配置设置确定文件的位置。
在上面的示例中,我返回了一个DefaultDirectoryBuilder
,但是我还有其他几个实现(请参阅下面的EdNrrDirectoryBuilder
方法)。
public IDirectoryBuilder DefaultValDatePricesDirectory(IContext arg)
{
return new DefaultDirectoryBuilder(
ConfigurationManager.AppSettings["VALDATE_PRICES_DIR"],
ConfigurationManager.AppSettings["VALDATE_PRICES_FILENAME"]);
}
public IDirectoryBuilder DefaultEDDatePricesDirectory(IContext arg)
{
return new DefaultDirectoryBuilder(
ConfigurationManager.AppSettings["EDDATE_PRICES_DIR"],
ConfigurationManager.AppSettings["EDDATE_PRICES_FILENAME"]);
}
public IDirectoryBuilder EdNrrDirectoryBuilder(IContext arg)
{
return new ExternalDirectoryBuilder(
ValuationDate,
ConfigurationManager.AppSettings["NRRDATE_DIR"],
ConfigurationManager.AppSettings["NRRDATE_PRICES_FILENAME"]);
}
我的问题是我需要配置文件中的值。现在,所有与配置相关的请求都在我的Ninject模块中受到限制。
如果我使用Ninject Factory方法创建IDirectoryBuilder
,我看到的方式是我需要在我的代码库中分散ConfigurationManager
个相关的调用。
如果我使用Ninject Provider方法,我将需要IDirectoryBuilder
的所有实现的提供程序,并且还更新了IDataConnection
的构造函数和实现。我的代码现在看起来也像(不是很干,类似于我目前的方法)。
Bind<IDirectoryBuilder>().ToProvider<DefaultDirectoryBuilderProvider>()
.WhenParentNamed("EDDatePricesXLConnection")
.WithConstructorArgument("baseDir", "someConfigValue")
.WithConstructorArgument("fileName", "someOtherConfigValue");
我的代码目前有一个非常一致的依赖链(使用NamedArguments):ICalculator
- &gt; IDataReader
- &gt; IDataConnection
- &gt; IDirectoryBuilder
- 这个让我相信必须有一些方法来重复创建这个链,而不必重复设置代码 - 我似乎无法弄清楚。还有一个额外的限制,因为我经常需要两个相同依赖关系链的实例 - 唯一的区别是不同的配置值。
答案 0 :(得分:0)
没有理由依赖任何Ninject特定技术(尽管在某些情况下,Provider可能是合适的(example of a provider here)。
简单的答案是,您为绑定表达式的前一个组件返回的内容(similar question)创建扩展方法。
在重新阅读您的问题时,我建议您查看Ninject.Extensions.Conventions哪些Bind
扩展方法可以让您按照建议的方式执行大肆Bind
。如果不是,我建议评论和识别你认为它没有解决的位。
答案 1 :(得分:0)
根据Ruben的评论,这是我目前的解决方案。我做的一个瘦是使用约定的概念,因此检索我的配置设置变得更容易。这过滤了使用Ninject Named
参数的大多数其他代码。
public void Load(){
BindDependencies<IDataReader<IList<Price>>, PricesDataReader
, IDataConnection<IList<PricesCsvRecord>>, PricesXLConnection
, DefaultDirectoryBuilder>
("ValDatePrices");
BindDependencies<IDataReader<IList<Price>>, PricesDataReader
, IDataConnection<IList<PricesCsvRecord>>, PricesXLConnection
, DefaultDirectoryBuilder>
("EDDatePrices");
// etc etc
}
public void BindDependencies<
TReaderBase, TReaderImpl,
TDataConnectionBase, TDataConnectionImpl,
TDirectoryBuilderFactoryImpl>
(string baseName)
where TReaderImpl : TReaderBase
where TDataConnectionImpl : TDataConnectionBase
{
DirectoryBuilderInfo dirInfor = GetSettings(baseName);
Bind<TReaderBase>()
.To(typeof(TReaderImpl))
.Named(baseName);
Bind<TDataConnectionBase>().To(typeof(TDataConnectionImpl))
.WhenParentNamed(baseName)
.Named(baseName + "XLConnection");
Func<IDirectoryBuilder> directoryBuilder = CreateDirectoryBuilderFunc<TDirectoryBuilderFactoryImpl>(dirInfor);
Bind<IDirectoryBuilder>()
.ToMethod(d => directoryBuilder())
.WhenParentNamed(baseName + "XLConnection");
}
private Func<IDirectoryBuilder> CreateDirectoryBuilderFunc<TDirectoryBuilderFactoryImpl>(DirectoryBuilderInfo dirInfor)
{
Func<IDirectoryBuilder> directoryBuilder =
() => CreateDefaultDirectoryBuilder(dirInfor.BaseDirectory, dirInfor.FileName);
if (typeof(TDirectoryBuilderFactoryImpl) == typeof(RiskDirectoryBuilderFactory))
{
directoryBuilder =
() => CreateRiskDirectoryBuilder(ValuationDate, dirInfor.BaseDirectory, dirInfor.FileName);
}
return directoryBuilder;
}
private DirectoryBuilderInfo GetSettings(string baseName)
{
var settingsName = baseName.ToUpperInvariant();
return new DirectoryBuilderInfo()
{
BaseDirectory = ConfigurationManager.AppSettings[settingsName + "_DIR"],
FileName = ConfigurationManager.AppSettings[settingsName + "_FILENAME"]
};
}