在 C# 中替代条件编译以进行数据库初始化
Alternative to Conditional Compilation in C# for Database Initialisation
我正在研究不依赖于#if #elif 的数据库初始化的替代实现......(不适用于 VS2017 已知问题中的 .Net 代码)select客户特定的数据库初始化程序。以下是一种对开发和 CI/CD 环境都合理的方法:
- 创建数据库初始化程序接口。
- 为包含实例的每个站点创建一个 c# 程序集项目
以上界面。
- 配置解决方案的数据库层以加载数据库初始化程序
运行时组装。
- 使用字符串参数 'siteName' 编写 powershell 脚本,构建
解决方案(基于 siteName 参数)重命名站点特定数据库
初始化程序,以便上述步骤可以在运行时加载程序集。
我有兴趣评估人们对这种方法的选择,这似乎是解决问题的可扩展解决方案,我唯一关心的是在运行时加载程序集,但我想强命名和代码签名程序集将降低风险.
这是我要更改的 DI 初始化类型,删除对 #if 的依赖....
private void DatabaseInitialiseDefinitions(ContainerBuilder builder)
{
#if site1
builder.RegisterType<site1ResourceIdentityDefinitions>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site1UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
#elif site2
builder.RegisterType<site2ResourceIdentityDefinition>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site2UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
#elif site3
builder.RegisterType<site3ResourceIdentityDefinition>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site3UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
}
如果您只需要在一个地方执行此操作 - 那么 factory pattern(请参阅替换编译器指令的示例)到 return 租户实现或类似的东西是一种选择。
如果是更多特定于租户的版本,直接使用 DI 比构建时简单得多。即使您只是选择性地注册其他租户实现,像 Autofac 这样的 DI 容器也会拉出最后匹配的注册,除非您请求 IEnumerable 服务。如果是我,我会使用依赖注入并将应用程序视为多租户。可能每个应用程序 运行 都是孤立的,但代码仍然是多租户的。
如果您有很多注册,我会使用子容器来保存特定于每个租户的注册。
如果您使用了 Autofac,那么这个扩展就可以了 - https://github.com/autofac/Autofac.AspNetCore.Multitenant or https://github.com/autofac/Autofac.Multitenant(如果不是 .Net Core)
我们已经将它与多种策略结合使用来识别租户 - 最简单的只是 app.config 中的一个配置设置,告诉它 运行 作为哪个租户。当前的基于主机名,因此所有租户 运行 在一个应用程序下。如果它是一个本地应用程序,我希望配置中的一个设置告诉它要成为哪个租户。
我正在研究不依赖于#if #elif 的数据库初始化的替代实现......(不适用于 VS2017 已知问题中的 .Net 代码)select客户特定的数据库初始化程序。以下是一种对开发和 CI/CD 环境都合理的方法:
- 创建数据库初始化程序接口。
- 为包含实例的每个站点创建一个 c# 程序集项目 以上界面。
- 配置解决方案的数据库层以加载数据库初始化程序 运行时组装。
- 使用字符串参数 'siteName' 编写 powershell 脚本,构建 解决方案(基于 siteName 参数)重命名站点特定数据库 初始化程序,以便上述步骤可以在运行时加载程序集。
我有兴趣评估人们对这种方法的选择,这似乎是解决问题的可扩展解决方案,我唯一关心的是在运行时加载程序集,但我想强命名和代码签名程序集将降低风险.
这是我要更改的 DI 初始化类型,删除对 #if 的依赖....
private void DatabaseInitialiseDefinitions(ContainerBuilder builder)
{
#if site1
builder.RegisterType<site1ResourceIdentityDefinitions>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site1UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
#elif site2
builder.RegisterType<site2ResourceIdentityDefinition>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site2UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
#elif site3
builder.RegisterType<site3ResourceIdentityDefinition>()
.As<IResourceIdentityDefinition>()
.SingleInstance();
builder.RegisterType<site3UserDefinitions>()
.As<IUserDefinitions>()
.SingleInstance();
}
如果您只需要在一个地方执行此操作 - 那么 factory pattern(请参阅替换编译器指令的示例)到 return 租户实现或类似的东西是一种选择。
如果是更多特定于租户的版本,直接使用 DI 比构建时简单得多。即使您只是选择性地注册其他租户实现,像 Autofac 这样的 DI 容器也会拉出最后匹配的注册,除非您请求 IEnumerable 服务。如果是我,我会使用依赖注入并将应用程序视为多租户。可能每个应用程序 运行 都是孤立的,但代码仍然是多租户的。
如果您有很多注册,我会使用子容器来保存特定于每个租户的注册。
如果您使用了 Autofac,那么这个扩展就可以了 - https://github.com/autofac/Autofac.AspNetCore.Multitenant or https://github.com/autofac/Autofac.Multitenant(如果不是 .Net Core)
我们已经将它与多种策略结合使用来识别租户 - 最简单的只是 app.config 中的一个配置设置,告诉它 运行 作为哪个租户。当前的基于主机名,因此所有租户 运行 在一个应用程序下。如果它是一个本地应用程序,我希望配置中的一个设置告诉它要成为哪个租户。