在 C# 中替代条件编译以进行数据库初始化

Alternative to Conditional Compilation in C# for Database Initialisation

我正在研究不依赖于#if #elif 的数据库初始化的替代实现......(不适用于 VS2017 已知问题中的 .Net 代码)select客户特定的数据库初始化程序。以下是一种对开发和 CI/CD 环境都合理的方法:

我有兴趣评估人们对这种方法的选择,这似乎是解决问题的可扩展解决方案,我唯一关心的是在运行时加载程序集,但我想强命名和代码签名程序集将降低风险.

这是我要更改的 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 中的一个配置设置,告诉它 运行 作为哪个租户。当前的基于主机名,因此所有租户 运行 在一个应用程序下。如果它是一个本地应用程序,我希望配置中的一个设置告诉它要成为哪个租户。