C# 如何使我的Ninject模块干燥?

C# 如何使我的Ninject模块干燥?,c#,ninject,C#,Ninject,我的Ninject模块中的以下代码重复了好几次。我可以使用什么方法和技术来减少重复的代码 public override void Load() { Bind<IDataReader<IList<Price>>>() .To<PricesDataReader>().Named("ValDatePrices"); Bind<IDataConnection<IList<PricesCsvRecord&g

我的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");
}
我的问题是我需要配置文件中的值。现在,所有与配置相关的请求都限制在我的Ninject模块中

如果我使用Ninject工厂方法来创建
IDirectoryBuilder
s,我认为我需要将
ConfigurationManager
相关调用分散在我的代码库中

如果使用Ninject提供程序方法,我将需要
IDirectoryBuilder
s的所有实现的提供程序,并更新
IDataConnection
的构造函数和实现。我的代码现在看起来也像(不是很枯燥,与我当前的方法类似)

Bind().ToProvider()
.WhenParentNamed(“EDDatePricesXLConnection”)
.WithConstructorArgument(“baseDir”、“someConfigValue”)
.WithConstructorArgument(“文件名”、“其他配置值”);

我的代码目前有一个非常一致的依赖链(使用NamedArguments):
ICalculator
->
IDataReader
->
IDataConnection
->
IDirectoryBuilder
-这让我相信一定有某种方法可以重复创建此链,而不必重复设置代码-我似乎无法理解。还有一个额外的限制,我通常需要相同依赖链的两个实例——唯一的区别是不同的配置值。

没有理由依赖任何特定于Ninject的技术(尽管在某些情况下,a可能是合适的()

简单的答案是为绑定表达式的前面组件返回的内容创建扩展方法()



在重读你的问题时,我建议看看哪些有大量的
Bind
扩展方法可以让你按照你建议的方式进行bulk
Bind
操作。如果没有,我建议你评论并确定你认为它没有解决的位。

基于鲁本的评论,这是我目前的解决方案我做的一件事是使用约定的概念,这样检索配置设置就变得更容易了。这会过滤掉使用Ninject
命名的
参数的大多数其他代码

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"]
     };
 }
public void Load(){
绑定依赖项
(“ValDatePrices”);
绑定依赖项
(“EDDatePrices”);
//等等
}
公共无效绑定依赖项<
TReaderBase,TReaderImpl,
TDataConnectionBase,TDataConnectionImpl,
tDirectory BuilderFactoryImpl>
(字符串baseName)
其中TReaderImpl:TReaderBase
其中TDataConnectionImpl:TDataConnectionBase
{
DirectoryBuilderInfo dirInfor=GetSettings(baseName);
绑定()
.至(类型(踏板式)
.命名(基本名称);
Bind()到(typeof(TDataConnectionImpl))
.WhenParentName(基本名称)
.命名(baseName+“XLConnection”);
Func directoryBuilder=CreateDirectoryBuilderFunc(dirInfor);
绑定()
.ToMethod(d=>directoryBuilder())
.WhenParentNamed(baseName+“XLConnection”);
}
私有函数CreateDirectoryBuilderFunc(DirectoryBuilderInfo dirInfor)
{
Func目录生成器=
()=>CreateDefaultDirectoryBuilder(dirInfor.BaseDirectory,dirInfor.FileName);
if(typeof(tdirectorybuilderfactorympl)=typeof(RiskDirectoryBuilderFactory))
{
目录生成器=
()=>CreateRiskDirectoryBuilder(估价日期,dirInfor.BaseDirectory,dirInfor.FileName);
}
返回目录生成器;
}
private DirectoryBuilderInfo GetSettings(字符串baseName)
{
var settingsName=baseName.ToUpperInvariant();
返回新的DirectoryBuilderInfo()
{
BaseDirectory=ConfigurationManager.AppSettings[设置名称+“\u目录”],
FileName=ConfigurationManager.AppSettings[设置名称+“\u FileName”]
};
}

另请参见Hi Ruben-请您提供一个快速示例或一些关于在我的案例中使用扩展的入门指导。我已经阅读了Wiki,但没有任何可行的解决方案。@Ahmad没有谈论任何惊天动地的事情。步骤1只是一个方法,它将属于一起的3个绑定块包装起来。然后,如果当/有剩余序列时,会出现重复,请创建一个将这两者结合在一起的扩展方法。您在
EdNrrDirectoryBuilder
中使用
evaluationdate
,这表明事情并不完全一致。但是,反省一下,很难说您的配置序列是否规则到可以使用约定适当。如果您的问题过于宽泛,无法给出清晰的答案,我会立即删除此答案。我根据您的评论创建了一个解决方案-看起来不错。有一件事:依赖项反转原则:-您应该将
Func
传递到
BindDependencies
中,而不必让它调用带有特殊情况的助手。然后做一个通过默认值的重载,并在大多数情况下使用它。如果你还没有得到manning.com/seemann
Bind<IDirectoryBuilder>().ToProvider<DefaultDirectoryBuilderProvider>()
    .WhenParentNamed("EDDatePricesXLConnection")
    .WithConstructorArgument("baseDir", "someConfigValue")
    .WithConstructorArgument("fileName", "someOtherConfigValue");
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"]
     };
 }