在.NET中创建高级控制台应用程序

介绍

在本文中,我将举一个例子,说明如何使用SimpleSoft.Hosting实现更高级的控制台应用程序  这个想法是通过利用最近的Microsoft.Extensions。*包,但没有太多的样板代码,更容易设置依赖注入,记录和导入应用程序设置这些概念类似于Microsoft.AspNetCore.Hosting包,但没有不必要的ASP.NET依赖关系,并且在创建Windows服务,实用工具,自主托管WCF应用程序或您可能拥有的其他需求时应该很有用。

在这种情况下,该示例是一个简单的控制台应用程序,它执行一些定期的Web请求。从应用程序设置读取地址和批处理延迟,NLog用于登录文件,AutoFac是依赖关系注入容器。

使用代码

该应用程序主要分为三类:

  • Program - 控制台应用程序的入口点;
  • HttpMonitorStartup - 配置类,注册和配置所有必需的依赖项;
  • HttpMonitorHost - 主机入门点类;

程序

由于这是一个控制台应用程序,我将首先解释入门点类:

 
 
  1.     public class Program
  2.     {
  3.         private static readonly CancellationTokenSource TokenSource;
  4.  
  5.         static Program()
  6.         {
  7.             TokenSource = new CancellationTokenSource();
  8.             Console.CancelKeyPress += (sender, args) =>             {
  9.                 TokenSource.Cancel();
  10.                 args.Cancel = true;
  11.             };
  12.         }
  13.  
  14.         public static int Main(string[] args) =>             MainAsync(args, TokenSource.Token).ConfigureAwait(false).GetAwaiter().GetResult();
  15.  
  16.         private static async Task<int> MainAsync(string[] args, CancellationToken ct)
  17.         {
  18.             ExecutionResult result;
  19.  
  20.             var loggerFactory = new LoggerFactory()
  21.                 .AddConsole(LogLevel.Trace, true);
  22.  
  23.             var logger = loggerFactory.CreateLogger<Program>();
  24.  
  25.             try             {
  26.                 logger.LogDebug("Preparing the host builder");
  27.  
  28.                 using (var hostBuilder = new HostBuilder("HTTPMONITOR_ENVIRONMENT")
  29.                     .UseLoggerFactory(loggerFactory)
  30.                     .UseStartup<HttpMonitorStartup>()
  31.                     .ConfigureConfigurationBuilder(p =>                     {
  32.                         p.Builder.AddCommandLine(args);
  33.                     }))
  34.                 {
  35.                     await hostBuilder.RunHostAsync<HttpMonitorHost>(ct);
  36.                 }
  37.  
  38.                 result = ExecutionResult.Success;
  39.             }
  40.             catch (TaskCanceledException)
  41.             {
  42.                 logger.LogWarning("The application execution was canceled");
  43.                 result = ExecutionResult.Canceled;
  44.             }
  45.             catch (Exception e)
  46.             {
  47.                 logger.LogCritical(0, e, "Unexpected exception has occurred");
  48.                 result = ExecutionResult.Failed;
  49.             }
  50.             logger.LogInformation("Application terminated [{result}]. Press <enter> to exit...", result);
  51.             Console.ReadLine();
  52.  
  53.             return (int) result;
  54.         }
  55.  
  56.         private enum ExecutionResult
  57.         {
  58.             Success = 0,
  59.             Failed = 1,
  60.             Canceled = 2         }
  61.     }

ILoggerFactory 最初的建设者之外创建的,因为我想至少包括在控制台每个日志。这不是一个要求,因为如果没有设置,构建器将在构建主机时使用默认工厂,没有任何提供者。我还使用环境变量  HTTPMONITOR_ENVIRONMENT来决定主机在哪个环境中运行。

在这个例子中,我使用一个自定义IHostStartup 类来注册和配置所有的应用依赖。有一些方法可以将任何支持的配置处理程序直接添加到构建器中,但是我更希望将代码保存在主方法简洁中。请注意,我附加一个第二个IConfigurationBuilder处理程序来将参数包含在配置中,但是我可以很容易地将它们作为参数传递给启动类。

然后,我只是运行主机。如果类没有手动注册到服务集合中,构建器将自动添加一个作用域生命周期,因此它将包含在IHostRunContext<THost>实例中。

当建立主机时,管道如下:

  1. 处理程序IConfigurationBuilder,可以访问IHostingEnvironment;
  2. 处理程序IConfigurationRoot,可以访问IHostingEnvironment;
  3. 处理程序ILoggerFactory,可以访问IConfiguration 和IHostingEnvironment;
  4. 处理程序IServiceCollection,可以访问ILoggerFactoryIConfiguration 和IHostingEnvironment;
  5. 构建IServiceProvider具有访问IServiceCollectionILoggerFactoryIConfiguration 和IHostingEnvironment;
  6. 的处理程序IServiceProvider能够访问所述,IServiceProviderILoggerFactoryIConfiguration 和IHostingEnvironment;

注意实例  ILoggerFactoryIConfigurationRoot 并IHostingEnvironment 自动注册到容器中。

备注:如果要配置记录器工厂,配置或任何其他要求,并且需要知道当前的环境或目录,并希望确保与主机构建器使用相同的属性,则可以始终HostingEnvironment通过使用构造函数创建  实例或静态方法  HostingEnvironment.BuildDefault ,并将环境作为构建器的参数传递。例:

 
 
  1. var loggerFactory = new LoggerFactory()
  2.     .AddConsole(LogLevel.Trace, true)
  3.     .AddNLog(); var env = HostingEnvironment.BuildDefault("HTTPMONITOR_ENVIRONMENT"); var nlogConfigFile = env.ContentRootFileProvider.GetFileInfo($"nlog.{env.Name}.config"); if (!nlogConfigFile.Exists)
  4.     nlogConfigFile = env.ContentRootFileProvider.GetFileInfo("nlog.config");
  5.  
  6. loggerFactory.ConfigureNLog(nlogConfigFile.PhysicalPath); var builder = new HostBuilder(env).UseLoggerFactory(loggerFactory);

HttpMonitorStartup

尽管不需要,一个启动类可以用来聚合所有的主机设置:

 
 
  1.     public class HttpMonitorStartup : HostStartup
  2.     {
  3.         public override void ConfigureConfigurationBuilder(IConfigurationBuilderParam param)
  4.         {
  5.             param.Builder
  6.                 .SetBasePath(param.Environment.ContentRootPath)
  7.                 .AddJsonFile("appsettings.json", false, true)
  8.                 .AddJsonFile($"appsettings.{param.Environment.Name}.json", true, true)
  9.                 .AddEnvironmentVariables();
  10.         }
  11.  
  12.         public override void ConfigureLoggerFactory(ILoggerFactoryHandlerParam param)
  13.         {
  14.             var nlogConfigFile = param.Environment.ContentRootFileProvider.GetFileInfo($"nlog.{param.Environment.Name}.config");
  15.             if (!nlogConfigFile.Exists)
  16.                 nlogConfigFile = param.Environment.ContentRootFileProvider.GetFileInfo("nlog.config");
  17.  
  18.             param.LoggerFactory
  19.                 .AddNLog()
  20.                 .ConfigureNLog(nlogConfigFile.PhysicalPath);
  21.         }
  22.  
  23.         public override void ConfigureServiceCollection(IServiceCollectionHandlerParam param)
  24.         {
  25.             param.ServiceCollection
  26.                 .AddOptions()
  27.                 .Configure<HttpMonitorOptions>(param.Configuration)
  28.                 .AddSingleton(s => s.GetRequiredService<IOptions<HttpMonitorOptions>>().Value);
  29.  
  30.             param.ServiceCollection
  31.                 .AddSingleton(s => new HttpClient())
  32.                 .AddSingleton<IUrlRequester, UrlRequester>();
  33.         }
  34.  
  35.         public override IServiceProvider BuildServiceProvider(IServiceProviderBuilderParam param)
  36.         {
  37.             var container = new ContainerBuilder();
  38.             container.Populate(param.ServiceCollection);
  39.             return new AutofacServiceProvider(container.Build());
  40.         }
  41.     }

就像ASP.NET Core一样,您可以有条件地加载设置,配置应用程序日志记录或替换默认容器实现。抽象类  HostStartup 使得更容易仅覆盖您的设置所需的内容。

HttpMonitorHost

在依赖注入容器的范围内运行的应用程序主机,这意味着您现在可以像任何ASP.NET应用程序一样布线。在这种情况下,我只需获取应用程序选项并开始制作HTTP请求。

 
 
  1.     public class HttpMonitorHost : IHost
  2.     {
  3.         private readonly HttpMonitorOptions _options;
  4.         private readonly IUrlRequester _urlRequester;
  5.         private readonly ILogger<HttpMonitorHost> _logger;
  6.  
  7.         public HttpMonitorHost(HttpMonitorOptions options, IUrlRequester urlRequester, ILogger<HttpMonitorHost> logger)
  8.         {
  9.             _options = options;
  10.             _urlRequester = urlRequester;
  11.             _logger = logger;
  12.         }
  13.  
  14.         public async Task RunAsync(CancellationToken ct)
  15.         {
  16.             for (var i = 0; i < _options.MaximumBatches; i++)
  17.             {
  18.                 _logger.LogDebug("Sending a batch of requests");
  19.                 await Task.WhenAll(_options.Urls.Select(url => _urlRequester.RequestAsync(url, ct)));
  20.  
  21.                 _logger.LogDebug("Waiting for the next batch time");
  22.                 await Task.Delay(_options.BatchDelayInMs, ct);
  23.             }
  24.  
  25.             _logger.LogDebug("Maximum of {maximumBatches} batches have been made", _options.MaximumBatches);
  26.         }
  27.     }

执行

运行应用程序时,应该看到如下输出:

结论

本文介绍了如何使用SimpleSoft.Hosting包开发高级控制台应用程序  由于它使用最新的Microsoft扩展程序包,第三方的支持是伟大的,使其成为一个要记住的选项。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值