Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager' while attempting to activate 'PluginCore.PluginControllerManager'.' #1

Open
yiyungent opened this issue Aug 9, 2021 · 4 comments
Labels
bug Something isn't working

Comments

@yiyungent
Copy link
Owner

yiyungent commented Aug 9, 2021

使用 环境变量 方式 指定承载启动程序集后,报错

System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager' while attempting to activate 'PluginCore.PluginControllerManager'.'

发生在

PluginManager pluginManager = scope.ServiceProvider.GetService<PluginManager>();

原因分析

由于外部承载启动程序集 (PluginCore) 先注册服务 ConfigureServices(IServiceCollection services), 而在这其中 尝试了一次 获取 ApplicationPartManager,但此时主程序 还没有注册服务 ApplicationPartManager ,导致无法解析

@yiyungent yiyungent added the bug Something isn't working label Aug 9, 2021
@yiyungent
Copy link
Owner Author

yiyungent commented Aug 9, 2021

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();
            });
        }
    }
}

@yiyungent
Copy link
Owner Author

yiyungent commented Aug 9, 2021

源代码,

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();

@yiyungent
Copy link
Owner Author

yiyungent commented Aug 9, 2021

外部先的问题就在于,有些service获取不到,因为是在主程序中注册的,你可能会说在外部注册,但有些必须单例,我试过了,如ApplicationPartManager,会变成两个

实际是先外部的注册服务 ( ConfigureServices(IServiceCollection services) ),再内部注册服务,再外部注册中间件 ( Configure(IApplicationBuilder app) ),再内部注册中间件

我需要在外部获取到主程序的服务,so,因此必须外部后

@yiyungent
Copy link
Owner Author

yiyungent commented Aug 9, 2021

承载启动程序集

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant