Skip to main content

使用IHostingStartup从外部库或者包添加功能或者配置

分类:  Asp.net Core入门 标签:  #Asp.Net core基础 #基础 #Web 发布于: 2023-06-04 20:11:11

我们前一章学习了ASP.net CoreStartup类,在前一章我们提及了利用IHostingStartup接口从外部的库或者包给现有的应用添加新的功能或者配置, 我们本节来介绍和学习一下这个功能。

IHostingStartup接口定义

我们先看一下接口IHostingStartup接口的定义:

public interface IHostingStartup
{
	public void Configure(IWebHostBuilder);
}

从接口的定义可以看到该接口仅仅只有一个方法Configure, 参数是IWebHostBuilder

外部库或者类定义的一般步骤

要给其他应用提供在初始化的时候添加配置,需要定义一个库或者不带应用入口的控制台应用,在这个库或者应用里,必须要符合两个条件:

  • 需要一个实现了接口IHostingStartup的类。
  • 在这个类定义上要使用属性标明该库或者应用可以给其他应用在初始化的时候增加配置:assembly: HostingStartup(typeof(namespace.className))
  • 在需要使用该配置外部库或者包的应用上通过指定环境变量或者代码指定需要启用的程序集名称
  • 通过添加对外部库或者外部包的引用或者将外部包放在runtime store中激活外部配置。

创建一个实现了IHostingStartupclass library

例如我们来创建一个类库。

dotnet new  classlib -n Demo2.libs
cd Demo2.libs

然后使用编辑器打开这个项目, 打开类Class1.cs

注意: 我们需要实现接口IHostingStartup
这里要仔细观察一下在实现IHostingStartup的时候,我只有一个Configure方法需要实现,同时它的参数是IWebHostBuilder
在这个方法里访问IConfiguration有两个办法:

  • 使用builder的ConfigureAppConfiguration()方法,取得IConfiguration`对象。
  • 使用builder的UseConfiguration方法
using System;
using Microsoft.AspNetCore.Hosting;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;

[assembly: HostingStartup(typeof(Demo2.libs.Class1))]
namespace Demo2.libs
{
    public class Class1: IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
             builder.ConfigureAppConfiguration(config =>
            {
                var dict = new Dictionary<string, string>
                {
                    {"DevAccount_FromLibrary", "DEV_1111111-1111"},
                    {"ProdAccount_FromLibrary", "PROD_2222222-2222"}
                };

                config.AddInMemoryCollection(dict);
            });

	    //访问配置的第二个方法:
	    dict = new Dictionary<string, string>
            {
            {"ConfigurationKey2", 
                "From IHostingStartup: Lower priority " +
                "than the app's configuration."},
           };

        var builtConfig = new ConfigurationBuilder()
            .AddInMemoryCollection(dict)
            .Build();

        builder.UseConfiguration(builtConfig);


    }
}

注意
从这个实例可以观察到,是如何定义这个库的, 需要我们注意的是我们已经在这个类库中使用了属性指定了需要IHostingStart
[assembly: HostingStartup(typeof(Demo2.libs.Class1))]

创建需要外部程序集配置的实际应用

然后我们再创建一个基于Razor的web项目:

dotnet new webapp -n Demo2.web
cd Demo2.web
dotnet add reference ..\Demo2.libs\Demo2.libs.csproj 

注意
我们这里直接通过给项目添加外部库的引用,激活了外部程序集的扫描,请记得我们之前概括的激活的两个方法:

  • 通过应用外部库或者外部包
  • 将外部包放入到runtime store

然后使用编辑器编辑Pages/index.cshtml.cs, 内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;

namespace Demo2.web.Pages
{
	public class IndexModel : PageModel
	{

		public IndexModel(IConfiguration config, ILogger<IndexModel> logger)
		{
			ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
			ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
			ServiceKey_Development_Package = config["DevAccount_FromPackage"];
			ServiceKey_Production_Package = config["ProdAccount_FromPackage"];

            _logger = logger;
		}

		public string ServiceKey_Development_Library { get; private set; }
		public string ServiceKey_Production_Library { get; private set; }
		public string ServiceKey_Development_Package { get; private set; }
		public string ServiceKey_Production_Package { get; private set; }

		public void OnGet()
		{
		}

		private readonly ILogger<IndexModel> _logger;

	}
}

打开页面Pages/index.cshtml, 添加引用:

 <ul>
                    <li><b>Development Service Key from Package</b>: @Model.ServiceKey_Development_Package</li>
                    <li><b>Production Service Key from Package</b>: @Model.ServiceKey_Production_Package</li>
                    <li><b>Development Service Key from Library</b>: @Model.ServiceKey_Development_Library</li>
                    <li><b>Production Service Key from Library</b>: @Model.ServiceKey_Production_Library</li>

    </ul>

最后一步,指定应用需要引用的外部程序集,这里也有两个方法:

  • 设定环境变量:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES 的值等于你需要引用的程序集
  • 在代码Progam.cs的代码里通过IWebBuilderUseSetting方法来指定

我们这里通过第二种方法,因此打开你的Program.cs, 文件,做如下修改:

      public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                    .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "Demo2.libs")
                    .UseStartup<Startup>();
                });

这样我们运行该应用,就能看到如下的效果:



至此我们已经介绍完了必要的步骤,另外需要提到的是外部包的创建,关于外部包实际上和class library基本一致,但是不能有程序入口,也就是包含Main方法的不要有就可以了。

Runtime Store

使用Runtime Store无需在应用中添加引用就可以实现激活三方程序集的配置,但是这个非常依赖环境,因此如果是确定环境配置不变,可以考虑采用这个办法,关于Runtime Store, 您可以参考如下的文档:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/platform-specific-configuration?view=aspnetcore-5.0#activation
https://docs.microsoft.com/en-us/dotnet/core/deploying/runtime-store