Open yiyungent opened 3 years ago
namespace AspNetCore3_1
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "PluginCore");
webBuilder.UseStartup<Startup>();
});
}
}
在 Program.cs
中指定承载启动程序集,然而无论 与 UseStartup<Startup>()
先后顺序如何,始终先执行 外部承载启动程序集
webBuilder.UseStartup<Startup>()
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "PluginCore");
依旧不改变顺序
[assembly: HostingStartup(typeof(PluginCore.PluginCoreHostingStartup))]
namespace PluginCore
{
/// <summary>
/// https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/host/platform-specific-configuration?view=aspnetcore-5.0
/// </summary>
public class PluginCoreHostingStartup : IHostingStartup
{
public PluginCoreHostingStartup()
{
}
public void Configure(IWebHostBuilder builder)
{
//builder.ConfigureAppConfiguration(config =>
//{
//});
// 注意: 无论是通过 Program.cs 中 webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "PluginCore");
// 还是 通过环境变量 指定承载启动程序集, 都是先执行 外部的承载启动程序集, 再执行主程序的 Startup.cs, 因此在这时, 有些 service 还没有注册
// TODO: 不知道, 重复 Add, Use 会导致什么, 没有做防止重复
builder.ConfigureServices(services =>
{
// fixed: https://github.com/yiyungent/PluginCore/issues/1
// System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager'
// TODO: 不确定, 这样是否可行, 事实上之后主程序还会 Add 一次, 不知道是否会导致存在多个 实例
// 失败: 不是一个实例, 导致无法改变 Controller
//Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager applicationPartManager =
// new Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager();
//services.AddSingleton<Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager>(applicationPartManager);
services.AddPluginCore();
});
builder.Configure(app =>
{
app.UsePluginCore();
});
}
}
}
源代码,
Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager
注册处
var partManager = new ApplicationPartManager();
partManager.ApplicationParts.Add(CompiledRazorAssemblyApplicationPartFactory.GetDefaultApplicationParts(viewsAssembly).Single());
var builder = services
.AddSingleton<ILoggerFactory, NullLoggerFactory>()
.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>()
.AddSingleton<DiagnosticSource>(listener)
.AddSingleton(listener)
.AddSingleton<IWebHostEnvironment, BenchmarkHostingEnvironment>()
.AddSingleton<ApplicationPartManager>(partManager)
.AddScoped<BenchmarkViewExecutor>()
.AddMvc();
外部先的问题就在于,有些service获取不到,因为是在主程序中注册的,你可能会说在外部注册,但有些必须单例,我试过了,如ApplicationPartManager,会变成两个
实际是先外部的注册服务 (
ConfigureServices(IServiceCollection services)
),再内部注册服务,再外部注册中间件 (Configure(IApplicationBuilder app)
),再内部注册中间件
我需要在外部获取到主程序的服务,so,因此必须外部后
使用
环境变量
方式 指定承载启动程序集后,报错发生在
原因分析
由于外部承载启动程序集 (
PluginCore
) 先注册服务ConfigureServices(IServiceCollection services)
, 而在这其中 尝试了一次 获取ApplicationPartManager
,但此时主程序 还没有注册服务ApplicationPartManager
,导致无法解析