16

asp.net core 3.x 模块化开发之HostingStartup

 4 years ago
source link: http://www.cnblogs.com/jionsoft/p/12183471.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

我们希望将一个项目(dll)看做一个模块/插件,一个模块往往需要在应用启动时做一些初始化工作,比如向IOC容器添加一些服务,为应用配置对象添加自己的数据源;也希望在应用关闭时做一些收尾工作,asp.net core为我们提供了这种机制,先来看看如何使用,再讲讲原理。

如何使用?

1、创建asp.net core 3.1的web应用程序,WebApplication6

2、创建我们的模块/插件项目,一个Standard2.1项目叫ClassLibrary2

Yv26FnZ.png!web

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))]

QbMBBjN.png!web

6、在主程序WebApplication6中设置环境变量,

VVBbQfy.png!web

除了这样配置,我们也可以在主程序的Program.main配置主机时手动覆盖配置值,以达到设置插件关联的程序集的目的,多个插件程序集用分号“;”分割

1 public static IHostBuilder CreateHostBuilder(string[] args) =>
2             Host.CreateDefaultBuilder(args)
3             .ConfigureWebHostDefaults(webBuilder =>{
4                     webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "ClassLibrary2");
5                     webBuilder.UseStartup<Startup>();
6                 });

还可以使用webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "ClassLibrary3");排出一些程序集,不把这些程序集当做插件来加载

原理是啥?

程序启动时会根据环境变量找到对应的插件程序集

根据程序集找到关联的 HostingStartupAttribute

通过 HostingStartupAttribute拿到插件启动类并调用其Confiure方法

方法内部可以做此插件的初始化工作、向主机IOC容器注册各种服务、设置应用配置的数据源等

多个模块的启动顺序是啥?

按配置的顺序加载模块的,所以最少依赖的模块应该写在前面,这个设计不如abp

模块直接如何通讯?

办法1、直接引用,配置时最好将被依赖的模块放前面

办法2、不添加直接引用关系,而用中间层实现

如添加一个中间项目,定义各种接口,由模块B来实现,在模块B中向容器注册自己的服务。模块A引用中间类库,直接在使用地方注入接口就ok啦

应用关闭时模块如果做一些收尾工作?

可以定义一个应用生命周期事件处理程序(实现IHostedApplicationLifetime),在不同事件中定义此模块的收尾工作。然后在模块启动类中向IOC注册这个服务。但这样有个问题,默认的生命周期事件处理程序被我们替换掉了,所以我们的类应该用构造函数注入IHostedApplicationLifetime,然后再调用它一次

每次写点东西都语无伦次,哈哈


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK