我们希望将一个项目 (dll) 看做一个模块 / 插件, 一个模块往往需要在应用启动时做一些初始化工作, 比如向 IoC 容器添加一些服务, 为应用配置对象添加自己的数据源; 也希望在应用关闭时做一些收尾工作, ASP.NET core 为我们提供了这种机制, 先来看看如何使用, 再讲讲原理.
如何使用?
1, 创建 ASP.NET core 3.1 的 web 应用程序, WebApplication6
2, 创建我们的模块 / 插件项目, 一个 Standard2.1 项目叫 ClassLibrary2
3, 在插件项目 ClassLibrary2 中定义实现 IHostingStartup 的类
- 1 public class HostingStartup : IHostingStartup
- 2 {
- 3 public void Configure(IWebHostBuilder builder)
- 4 {
- 5 // 向 IoC 容器添加或替换各种服务
- 6 builder.ConfigureServices((c,b)=> {
- 7 b.AddSingleton<Class1>();
- 8 });
- 9 // 为应用配置对象添加更多数据源
- 10 builder.ConfigureAppConfiguration(c => {
- 11 c.AddInMemoryCollection(new Dictionary<string, string> { {"a","tttt" } });
- 12 });
- // 处理当前模块的其它初始化操作
- 13 }
- 14 }
5, 在插件项目 ClassLibrary2 中随便找个类文件中, 设置[assembly: HostingStartupAttribute(typeof(ClassLibrary2.HostingStartup))]
6, 在主程序 WebApplication6 中设置环境变量,
除了这样配置, 我们也可以在主程序的 Program.main 配置主机时手动覆盖配置值, 以达到设置插件关联的程序集的目的, 多个插件程序集用分号 ";" 分割
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>{
- webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "ClassLibrary2");
- webBuilder.UseStartup<Startup>();
- });
还可以使用 webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "ClassLibrary3"); 排出一些程序集, 不把这些程序集当做插件来加载
原理是啥?
程序启动时会根据环境变量找到对应的插件程序集
根据程序集找到关联的 HostingStartupAttribute
通过 HostingStartupAttribute 拿到插件启动类并调用其 Confiure 方法
方法内部可以做此插件的初始化工作, 向主机 IoC 容器注册各种服务, 设置应用配置的数据源等
多个模块的启动顺序是啥?
按配置的顺序加载模块的, 所以最少依赖的模块应该写在前面, 这个设计不如 abp
模块之间如何通讯?
办法 1, 直接引用, 配置时最好将被依赖的模块放前面
办法 2, 不添加直接引用关系, 而用中间层实现
如添加一个中间项目, 定义各种接口, 由模块 B 来实现, 在模块 B 中向容器注册自己的服务. 模块 A 引用中间类库, 直接在使用地方注入接口就 ok 啦
应用关闭时模块如果做一些收尾工作?
可以定义一个应用生命周期事件处理程序(实现 IHostedApplicationLifetime), 在不同事件中定义此模块的收尾工作. 然后在模块启动类中向 IoC 注册这个服务. 但这样有个问题, 默认的生命周期事件处理程序被我们替换掉了, 所以我们的类应该用构造函数注入 IHostedApplicationLifetime, 然后再调用它一次
每次写点东西都语无伦次, 哈哈
来源: https://www.cnblogs.com/jionsoft/p/12183471.html