我有一个使用接口IBackend
与后端通信的应用程序。在生产环境中,我希望使用类ProdBackend : IBackend
作为接口的实现。在测试环境中,我希望使用TestBackend : IBackend
。
应用程序打包成一个zip文件,该文件必须与它是否部署在prod或测试环境中无关。
如何使应用程序使用IBackend
的不同实现,具体取决于它所部署的环境?
我是否可以通过简单地在两个环境中安装不同的.dll并将类命名为相同来实现此目的?
更新11:12 - 15/1 :
打包的应用程序不允许包含prod实现,即ProdBackend : IBackend
。因此,应用程序在编译时不知道ProdBackend : IBackend
。
答案 0 :(得分:1)
根据您的设置,有很多方法可以执行此操作。我能想到这些:
Envirnoment.MachineName
新建一个依赖项。
ProdBackend
的程序集和包含TestBackend
的程序集),则可以在部署应用程序时做出决定。您可以通过使用IOC容器用于连接依赖项(或其他方法)的插件目录来实现此目的。app.config
)。答案 1 :(得分:0)
使用相同接口的不同实现提供不同的DLL可以正常工作。
更优雅的解决方案是这样做,但添加一个服务定位器,提供您需要的实现。然后,您可以将服务定位器配置为根据您运行的平台返回实现。
有许多服务定位器,但是在Mono支持的所有平台上运行的简单服务定位器是TinyIOC
答案 2 :(得分:0)
测试环境的全部目的是让您尽可能合理地确保在将某些内容部署到生产环境时它将正常工作。如果您有一组在Test上执行的代码以及在部署到Production时执行的另一组代码,那么您如何实现该目标?
从本质上讲,从代码角度来看,测试和生产之间的区别应该只是配置(不同的数据库连接,可能更详细的测试日志等)。否则,基本上,你将未经测试的代码部署到Production,在我看来,这是为可能的灾难播下种子。
答案 3 :(得分:0)
有一个概念:Contextual Binding - 由几乎所有依赖注入容器实现。在实践中,这意味着您可以将条件添加到绑定中。以下是使用ninject
的示例例如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
根据Ninject download,Mono有一个版本,但你也可以在其他DI容器中实现相同的功能