获取Startup.cs对象的引用

7

下面是一个标准的ASP.NET Core应用程序的框架:

var config = new ConfigurationBuilder()
    .AddCommandLine(args)
    .AddEnvironmentVariables(prefix: "ASPNETCORE_")
    .Build();

var host = new WebHostBuilder()
    .UseConfiguration(config)
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .Build();

host.Run();

在这个片段中,ASP.NET Core工具实例化了Startup.cs类的一个实例。
.UseStartup<Startup>()

我的问题是如何获取已实例化的 Startup 对象的引用,以便将其插入到我的库/框架中。
背景是设置一些顶层框架并获取此交汇点(Startup.cs)的引用,其中所有请求都是由其发起的。
1个回答

10

如果你的Startup实现了IStartup接口,获取对它的引用就很容易:

var host = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

var startup = host.Services.GetService(typeof(IStartup)); // or from any other part of code using IServiceProvider.
然而,asp.net core并不要求您的启动类实现此接口。如果没有实现它,它将使用适配器模式将您的Startup类适配到IStartup接口。您仍将拥有一个IStartup实例,但它不会是您的Startup类。相反,它将是ConventionBasedStartup的一个实例。Asp.net core将探索您的启动类方法,找到ConfigureConfigureServices方法,并将它们传递给ConventionBasedStartup,后者将使它们适应IStartup接口。在这种情况下,不能通过重型反射检索您的启动类的实例,因为它实际上未存储在ConventionBasedStartup的任何字段(甚至是私有字段)中,只能通过委托引用访问。
简而言之-如果想获得您的Startup类的实例,请使其实现IStartup接口。
关于如何实现IStartup接口的更新:
public class Startup : IStartup
{
    public Startup(IHostingEnvironment env)
    {
        // constructor as usual
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void Configure(IApplicationBuilder app) {            
        app.UseMvc();
        // resolve services from container
        var env = (IHostingEnvironment) app.ApplicationServices.GetService(typeof(IHostingEnvironment));
        var logger = (ILoggerFactory)app.ApplicationServices.GetService(typeof(ILoggerFactory));
        logger.AddConsole(Configuration.GetSection("Logging"));
        logger.AddDebug();
        // etc
    }        

    public IServiceProvider ConfigureServices(IServiceCollection services) {
        services.AddMvc();
        // etc
        // return provider
        return services.BuildServiceProvider();
    }
}

谢谢,这看起来很有前途。我在Startup类中添加了IStartup作为接口,但是它对于ConfigureServices的返回类型报错了。问题是,在ConfigureServices中应该返回什么以匹配IStartup接口的要求?我对.NET还不熟悉。 - user2727195
谢谢,Visual Studio Code 抱怨缺少一些依赖项,例如 ConfigurationBuilderIConfigurationRoot。我使用生成器 yo aspnet 创建了一个基本的最简单的 Web 应用程序。希望在 Startup.cs 级别上实现最简单的实现,因为繁重的工作将在我的框架中完成。此外,我不想插入到 asp.net mvcmvc 中,因为我有自己的自定义实现。在最简单的级别上,我希望启动对象只是将传入的请求委托给我的框架。 - user2727195
请注意,我的示例仅展示了如何实现IStartup接口。IConfigurationRoot、Startup构造函数、UseMvc等仅作为占位符提供,以向您展示如何实现。这并不是必需的。只需根据提供的签名自行实现Configure和ConfigureServices即可。 - Evk
你好,能否请您也看一下这个链接:http://stackoverflow.com/questions/42062316/intercepting-and-delegating-requests-to-a-custom-object-library - user2727195
2
我尝试了这个解决方案,但它会创建一个新的启动实例。有什么建议吗? - Tom
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接