Saltar al contenido

Startup.cs en una aplicación de consola .NET Core autohospedada

La guía paso a paso o código que hallarás en este post es la solución más eficiente y efectiva que encontramos a tu duda o problema.

Solución:

Entonces me encontré con esta solución, inspirada por la respuesta aceptada:

Program.cs

public class Program

    public static void Main(string[] args)
    
        IServiceCollection services = new ServiceCollection();
        // Startup.cs finally :)
        Startup startup = new Startup();
        startup.ConfigureServices(services);
        IServiceProvider serviceProvider = services.BuildServiceProvider();

        //configure console logging
        serviceProvider
            .GetService()
            .AddConsole(LogLevel.Debug);

        var logger = serviceProvider.GetService()
            .CreateLogger();

        logger.LogDebug("Logger is working!");

        // Get Service and call method
        var service = serviceProvider.GetService();
        service.MyServiceMethod();
    

Startup.cs

public class Startup

    IConfigurationRoot Configuration  get; 

    public Startup()
    
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");

        Configuration = builder.Build();
    

    public void ConfigureServices(IServiceCollection services)
    
        services.AddLogging();
        services.AddSingleton(Configuration);
        services.AddSingleton();
    

appsettings.json


    "SomeConfigItem": 
        "Token": "8201342s223u2uj328",
        "BaseUrl": "http://localhost:5000"
    

MyService.cs

public class MyService : IMyService

    private readonly string _baseUrl;
    private readonly string _token;
    private readonly ILogger _logger;

    public MyService(ILoggerFactory loggerFactory, IConfigurationRoot config)
    
        var baseUrl = config["SomeConfigItem:BaseUrl"];
        var token = config["SomeConfigItem:Token"];

        _baseUrl = baseUrl;
        _token = token;
        _logger = loggerFactory.CreateLogger();
    

    public async Task MyServiceMethod()
    
        _logger.LogDebug(_baseUrl);
        _logger.LogDebug(_token);
    

IMyService.cs

public interface IMyService

    Task MyServiceMethod();

Todo .NET Core Las aplicaciones se componen de bibliotecas independientes y paquetes bien elaborados a los que puede hacer referencia y utilizar libremente en cualquier tipo de aplicación. Da la casualidad de que un Asp.net core La aplicación viene preconfigurada para hacer referencia a muchas de esas bibliotecas y expone un extremo http.

Pero si lo que necesita para su aplicación de consola es Inyección de dependencia, simplemente consulte la biblioteca correspondiente. Aquí hay una guía: http://andrewlock.net/using-dependency-injection-in-a-net-core-console-application/

Esta respuesta se basa en los siguientes criterios:

Me gustaría usar el nuevo host genérico CreateDefaultBuilder sin ninguna de las cosas web de ASP.NET, en una aplicación de consola simple, pero también ser capaz de eliminar la lógica de inicio en startup.cs para configurar AppConfiguration y servicios

Así que pasé la mañana averiguando cómo se podía hacer tal cosa. Esto es lo que se me ocurrió …

El único paquete nuget que requiere este método es Microsoft.Extensions.Hosting (en el momento de escribir este artículo estaba en la versión 3.1.7). Aquí hay un enlace al paquete nuget. Este paquete también es necesario para usar CreateDefaultBuilder(), por lo que es probable que ya lo hayas agregado.

Después de agregar la extensión (código de extensión en la parte inferior de la respuesta) a su proyecto, configura la entrada del programa para que se vea similar a esto:

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!

Añades un Startup.cs que debería verse así:

public class Startup

    public IConfiguration Configuration  get; 

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public void ConfigureServices(IServiceCollection services)
    
        // Configure your services here
    

Luego, configure sus servicios como lo haría en una aplicación ASP.NET Core típica (sin necesidad de tener instalado ASP.NET Core Web Hosting).

Proyecto de demostración

Reuní un proyecto de demostración de la consola .NET Core 3.1 haciendo todo tipo de cosas, como un IHostedService implementación, BackgroundService implementación, servicios transitorios / singleton. También me inyecté en IHttpClientFactory y IMemoryCache para una buena medida.

Clona ese repositorio y pruébalo.

Cómo funciona

Creé un método de extensión fuera de IHostBuilder que simplemente implementa el IHostBuilder UseStartup(this IHostBuilder hostBuilder) patrón al que todos estamos acostumbrados.

Ya que CreateDefaultBuilder() agrega todos los conceptos básicos, no queda mucho para agregar. Lo único que nos preocupa es conseguir la IConfiguration y creando nuestra cartera de servicios a través de ConfigureServices(IServiceCollection).

Código fuente del método de extensión

/// 
/// 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;
    

Aquí puedes ver las comentarios y valoraciones de los usuarios

Recuerda que puedes dar visibilidad a este artículo si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *