Startup.cs in a self-hosted .NET Core Console Application

后端 未结 7 911
情书的邮戳
情书的邮戳 2020-12-07 09:53

I have a self-hosted .NET Core Console Application.

The web shows examples for ASP.NET Core but i do not have a webserver. Just a simple c

7条回答
  •  天命终不由人
    2020-12-07 10:06

    This answer is based on the following criteria:

    I'd like to use the new Generic Host CreateDefaultBuilder without any of the ASP.NET web stuff, in a simple console app, but also be able to squirrel away the startup logic in startup.cs in order to configure AppConfiguration and Services

    So I spent the morning figuring out how you could do such a thing. This is what I came up with...

    The only nuget package this method requires is Microsoft.Extensions.Hosting (at the time of this writing it was at version 3.1.7). Here is a link to the nuget package. This package is also required to use CreateDefaultBuilder(), so chances are you already had it added.

    After you add the extension (extension code at bottom of answer) to your project, you set your program entry to look similar to this:

    using Microsoft.Extensions.Hosting;
    
    class Program
    {
        static async Task Main(string[] args)
        {
            var host = CreateHostBuilder(args).Build();
            await host.RunAsync();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseStartup(); // our new method!
    }
    

    You add a Startup.cs that should look like this:

    public class Startup
    {
        public IConfiguration Configuration { get; }
    
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public void ConfigureServices(IServiceCollection services)
        {
            // Configure your services here
        }
    }
    

    You then configure your services as you would in a typical ASP.NET Core application (without needing to have ASP.NET Core Web Hosting installed).

    Demo Project

    I put together a .NET Core 3.1 console demo project doing all kinds of things such as an IHostedService implementation, BackgroundService implementation, transient/singleton services. I also injected in IHttpClientFactory and IMemoryCache for good measure.

    Clone that repo and give it a shot.

    How It Works

    I created an extension method off of IHostBuilder which simply implements the IHostBuilder UseStartup(this IHostBuilder hostBuilder) pattern that we are all used to.

    Since CreateDefaultBuilder() adds in all the basics, there's not much left to add to it. The only thing we are concerned about is getting the IConfiguration and creating our service pipeline via ConfigureServices(IServiceCollection).

    Extension Method Source Code

    /// 
    /// Extensions to emulate a typical "Startup.cs" pattern for 
    /// 
    public static class HostBuilderExtensions
    {
        private const string ConfigureServicesMethodName = "ConfigureServices";
    
        /// 
        /// Specify the startup type to be used by the host.
        /// 
        /// The type containing an optional constructor with
        /// an  parameter. The implementation should contain a public
        /// method named ConfigureServices with  parameter.
        /// The  to initialize with TStartup.
        /// The same instance of the  for chaining.
        public static IHostBuilder UseStartup(
            this IHostBuilder hostBuilder) where TStartup : class
        {
            // Invoke the ConfigureServices method on IHostBuilder...
            hostBuilder.ConfigureServices((ctx, serviceCollection) =>
            {
                // Find a method that has this signature: ConfigureServices(IServiceCollection)
                var cfgServicesMethod = typeof(TStartup).GetMethod(
                    ConfigureServicesMethodName, new Type[] { typeof(IServiceCollection) });
    
                // Check if TStartup has a ctor that takes a IConfiguration parameter
                var hasConfigCtor = typeof(TStartup).GetConstructor(
                    new Type[] { typeof(IConfiguration) }) != null;
    
                // create a TStartup instance based on ctor
                var startUpObj = hasConfigCtor ?
                    (TStartup)Activator.CreateInstance(typeof(TStartup), ctx.Configuration) :
                    (TStartup)Activator.CreateInstance(typeof(TStartup), null);
    
                // finally, call the ConfigureServices implemented by the TStartup object
                cfgServicesMethod?.Invoke(startUpObj, new object[] { serviceCollection });
            });
    
            // chain the response
            return hostBuilder;
        }
    }
    

提交回复
热议问题