根据环境改变接口的实现

时间:2013-01-15 10:01:14

标签: c# dependency-injection mono

我有一个使用接口IBackend与后端通信的应用程序。在生产环境中,我希望使用类ProdBackend : IBackend作为接口的实现。在测试环境中,我希望使用TestBackend : IBackend

应用程序打包成一个zip文件,该文件必须与它是否部署在prod或测试环境中无关。

如何使应用程序使用IBackend的不同实现,具体取决于它所部署的环境?

我是否可以通过简单地在两个环境中安装不同的.dll并将类命名为相同来实现此目的?

更新11:12 - 15/1 : 打包的应用程序不允许包含prod实现,即ProdBackend : IBackend。因此,应用程序在编译时不知道ProdBackend : IBackend

4 个答案:

答案 0 :(得分:1)

根据您的设置,有很多方法可以执行此操作。我能想到这些:

  1. 计算机名称:如果您知道测试服务器的服务器名称(或约定),则可以根据Envirnoment.MachineName新建一个依赖项。
  2. 插件:如果您使用插件模型(通过构建包含ProdBackend的程序集和包含TestBackend的程序集),则可以在部署应用程序时做出决定。您可以通过使用IOC容器用于连接依赖项(或其他方法)的插件目录来实现此目的。
  3. 配置:您可以使用配置文件中的值来确定环境,然后使用该信息在两个实现之间进行选择。然后,在部署到prod环境时,您可以相应地调整配置文件(app.config)。

答案 1 :(得分:0)

使用相同接口的不同实现提供不同的DLL可以正常工作。

更优雅的解决方案是这样做,但添加一个服务定位器,提供您需要的实现。然后,您可以将服务定位器配置为根据您运行的平台返回实现。

有许多服务定位器,但是在Mono支持的所有平台上运行的简单服务定位器是TinyIOC

答案 2 :(得分:0)

测试环境的全部目的是让您尽可能合理地确保在将某些内容部署到生产环境时它将正常工作。如果您有一组在Test上执行的代码以及在部署到Production时执行的另一组代码,那么您如何实现该目标?

从本质上讲,从代码角度来看,测试和生产之间的区别应该只是配置(不同的数据库连接,可能更详细的测试日志等)。否则,基本上,你将未经测试的代码部署到Production,在我看来,这是为可能的灾难播下种子。

答案 3 :(得分:0)

有一个概念:Contextual Binding - 由几乎所有依赖注入容器实现。在实践中,这意味着您可以将条件添加到绑定中。以下是使用

的示例

定义'生产'环境条件

例如Environment.MachineName,或任何其他适合您的人:

private static readonly Func<bool> IsCurrentEnvironmentProduction = 
   () => Environment.MachineName == "Production.Server";

定义不同环境的绑定

public static IKernel InitializeKernel() 
{ 
    var kernel = new StandardKernel();

    // binding for production
    kernel
        .Bind<IBackend>()
        .To<ProdBackend>()
        .When(request => IsCurrentEnvironmentProduction());

    // binding for test environment
    kernel
        .Bind<IBackend>()
        .To<TestBackend>()
        .When(request => !IsCurrentEnvironmentProduction());

    return kernel; 
}

解析实例取决于环境

DI容器将为您完成所有工作

var backend = kernel.Get<IBackend>();

提供完整样本here

关于Mono的评论

根据Ninject download,Mono有一个版本,但你也可以在其他DI容器中实现相同的功能