根据环境改变接口的实现
本文关键字:实现 接口 改变 环境 | 更新日期: 2023-09-27 17:53:26
我有一个使用接口IBackend
与后端通信的应用程序。在生产环境中,我希望使用类ProdBackend : IBackend
作为接口的实现。在测试环境中,我希望使用TestBackend : IBackend
。
应用程序被打包到一个zip文件中,该文件必须独立于它是部署在prod环境还是测试环境中。
如何使应用程序根据其部署的环境使用不同的IBackend
实现?
我可以通过简单地在两个环境中安装不同的.dll并命名相同的类来做到这一点吗?
UPDATE 11:12 - 15/1:打包的应用程序不允许包含prod实现,即ProdBackend : IBackend
。因此,应用程序在编译时不知道ProdBackend : IBackend
。
根据您的设置,有许多方法可以做到这一点。我能想到这些:
-
机器名:如果您知道测试服务器的服务器名(或约定),您可以根据
Envirnoment.MachineName
新建依赖项。 -
Plugin:如果您使用插件模型(通过构建包含
ProdBackend
的程序集和包含TestBackend
的程序集),您可以在部署应用程序时做出决定。你可以有一个插件目录,你的IOC容器将使用它来连接依赖项(或其他方式)。 -
Configuration:您可以使用配置文件中的值来确定环境,然后使用该信息在两个实现之间进行选择。然后,在部署到prod环境时,可以相应地调整配置文件(
app.config
)。
为相同接口的不同实现提供不同的DLL将工作得很好。
一个更优雅的解决方案是这样做,但要添加一个提供所需实现的服务定位器。然后,您可以配置Service Locator以返回基于您所运行的平台的实现。
有很多服务定位器,但有一个简单的可以在Mono支持的所有平台上运行的是TinyIOC
测试环境的全部意义在于允许您尽可能合理地确定,当您将某些内容部署到生产环境时,它将正常工作。如果您有一组代码在测试中执行,而另一组代码在部署到生产环境时执行,那么您是如何实现这个目标的?
本质上,从代码的角度来看,测试和生产之间的区别应该只是配置(不同的数据库连接,可能在测试上更详细的日志记录,等等)。否则,从本质上讲,您是在将未经测试的代码部署到生产环境中,在我看来,这是在为可能的灾难播下种子。
有一个概念:上下文绑定——几乎所有依赖注入容器都实现了这个概念。在实践中,这意味着您可以在绑定中添加条件。下面是使用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>();
完整样本在这里
关于Mono的说明
根据Ninject下载,Mono有一个发布版本,但是你也可以在其他DI容器中实现相同的功能