Guest User

Sinnlos übertriebenes HelloWorld-Programm

a guest
May 23rd, 2020
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.27 KB | None | 0 0
  1. using Microsoft.Extensions.DependencyInjection;
  2.  
  3. using Newtonsoft.Json;
  4.  
  5. using System;
  6. using System.IO;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9.  
  10. public interface IMessageProvider
  11. {
  12.     Task<string> GetMessageAsync();
  13. }
  14. public interface IMessageViewer
  15. {
  16.     Task ShowMessageAsync(string message);
  17. }
  18. public interface IConfigReader
  19. {
  20.     Task<IConfig> LoadConfigAsync();
  21. }
  22. public interface IConfig
  23. {
  24.     public string MessageFilePath { get; }
  25. }
  26. public interface ICancelTokenSource
  27. {
  28.     CancellationToken Token { get; }
  29. }
  30. public interface IProgramRuntime
  31. {
  32.     Task StartAsync();
  33.     Task StopAsync();
  34. }
  35. public interface IProgramWorker
  36. {
  37.     Task DoWorkAsync();
  38. }
  39.  
  40. public class ConfigInfo
  41. {
  42.     public ConfigInfo(string configFilePath)
  43.     {
  44.         ConfigFilePath = configFilePath ?? throw new ArgumentNullException(nameof(configFilePath));
  45.     }
  46.  
  47.     public string ConfigFilePath { get; }
  48. }
  49.  
  50. public class CancelTokenSource : ICancelTokenSource
  51. {
  52.     private readonly CancellationTokenSource _realSource;
  53.  
  54.     public CancelTokenSource(CancellationTokenSource realSource)
  55.     {
  56.         _realSource = realSource ?? throw new ArgumentNullException(nameof(realSource));
  57.     }
  58.  
  59.     public CancellationToken Token => _realSource.Token;
  60. }
  61. public class ConfigMessageProvider : IMessageProvider
  62. {
  63.     private readonly IConfigReader _configProvider;
  64.     private readonly CancellationToken _cancelToken;
  65.  
  66.     public ConfigMessageProvider(IConfigReader configProvider, ICancelTokenSource cancelTokenSource)
  67.     {
  68.         if (cancelTokenSource == null)
  69.             throw new ArgumentNullException(nameof(cancelTokenSource));
  70.  
  71.         _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));
  72.         _cancelToken = cancelTokenSource.Token;
  73.     }
  74.  
  75.     public async Task<string> GetMessageAsync()
  76.     {
  77.         var config = await _configProvider.LoadConfigAsync();
  78.         return await File.ReadAllTextAsync(config.MessageFilePath, _cancelToken);
  79.     }
  80. }
  81. public class JsonConfigReader : IConfigReader
  82. {
  83.     private readonly ConfigInfo _configInfo;
  84.     private readonly CancellationToken _cancelToken;
  85.  
  86.     public JsonConfigReader(ConfigInfo configInfo, ICancelTokenSource cancelTokenSource)
  87.     {
  88.         if (cancelTokenSource == null)
  89.             throw new ArgumentNullException(nameof(cancelTokenSource));
  90.         _configInfo = configInfo ?? throw new ArgumentNullException(nameof(configInfo));
  91.         _cancelToken = cancelTokenSource.Token;
  92.     }
  93.  
  94.     public async Task<IConfig> LoadConfigAsync()
  95.     {
  96.         var configFilePath = _configInfo.ConfigFilePath;
  97.         var configJson = await File.ReadAllTextAsync(configFilePath, _cancelToken);
  98.         return JsonConvert.DeserializeObject<Config>(configJson);
  99.     }
  100.  
  101.     private class Config : IConfig
  102.     {
  103.         public string MessageFilePath { get; set; }
  104.     }
  105. }
  106. public class ConsoleMessageViewer : IMessageViewer
  107. {
  108.     public Task ShowMessageAsync(string message)
  109.     {
  110.         Console.WriteLine(message);
  111.         return Task.CompletedTask;
  112.     }
  113. }
  114. public class ProgramRuntime : IProgramRuntime, IDisposable
  115. {
  116.     private readonly Func<IServiceProvider, IProgramWorker> _workerFactory;
  117.     private readonly IServiceScopeFactory _scopeFactory;
  118.     private CancellationTokenSource _cancelTokenSource;
  119.     private Task _runtimeTask;
  120.  
  121.     public ProgramRuntime(IServiceScopeFactory scopeFactory, Func<IServiceProvider, IProgramWorker> workerFactory)
  122.     {
  123.         _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
  124.         _workerFactory = workerFactory ?? throw new ArgumentNullException(nameof(workerFactory));
  125.     }
  126.  
  127.     public async Task StartAsync()
  128.     {
  129.         await StopAsync();
  130.  
  131.         _cancelTokenSource = new CancellationTokenSource();
  132.  
  133.         _runtimeTask = Task.Factory.StartNew(
  134.             DoWorkLoop,
  135.             _cancelTokenSource.Token,
  136.             TaskCreationOptions.LongRunning,
  137.             TaskScheduler.Default)
  138.             .Unwrap();
  139.     }
  140.     public async Task StopAsync()
  141.     {
  142.         _cancelTokenSource?.Cancel();
  143.  
  144.         try
  145.         {
  146.             await (_runtimeTask ?? Task.CompletedTask);
  147.         }
  148.         catch (TaskCanceledException) { }
  149.  
  150.         _cancelTokenSource?.Dispose();
  151.         _runtimeTask?.Dispose();
  152.     }
  153.  
  154.     private async Task DoWorkLoop()
  155.     {
  156.         while(!_cancelTokenSource.IsCancellationRequested)
  157.         {
  158.             using (var scope = _scopeFactory.CreateScope())
  159.             {
  160.                 var worker = _workerFactory(scope.ServiceProvider);
  161.  
  162.                 await worker.DoWorkAsync();
  163.             }
  164.  
  165.             await Task.Delay(100, _cancelTokenSource.Token);
  166.         }
  167.     }
  168.  
  169.     public void Dispose()
  170.     {
  171.         _cancelTokenSource?.Dispose();
  172.         _runtimeTask?.Dispose();
  173.     }
  174. }
  175. public class ProgramWorker : IProgramWorker
  176. {
  177.     private readonly IMessageProvider _messageProvider;
  178.     private readonly IMessageViewer _messageViewer;
  179.  
  180.     public ProgramWorker(IMessageProvider messageProvider, IMessageViewer messageViewer)
  181.     {
  182.         _messageProvider = messageProvider ?? throw new ArgumentNullException(nameof(messageProvider));
  183.         _messageViewer = messageViewer ?? throw new ArgumentNullException(nameof(messageViewer));
  184.     }
  185.  
  186.     public async Task DoWorkAsync()
  187.     {
  188.         try
  189.         {
  190.             var message = await _messageProvider.GetMessageAsync();
  191.  
  192.             await _messageViewer.ShowMessageAsync(message);
  193.         }
  194.         catch (Exception ex)
  195.         {
  196.             await _messageViewer.ShowMessageAsync(ex.ToString());
  197.         }
  198.     }
  199. }
  200.  
  201. internal class Program
  202. {
  203.     private static async Task Main()
  204.     {
  205.         var configFilePath = "config.json";
  206.  
  207.         await PrepareTestState(configFilePath);
  208.  
  209.         var services = CreateServices(configFilePath);
  210.  
  211.         await RunProgram(services, TimeSpan.FromSeconds(10));
  212.     }
  213.     private static async Task RunProgram(IServiceProvider services, TimeSpan duration)
  214.     {
  215.         var runtime = services.GetRequiredService<IProgramRuntime>();
  216.  
  217.         await runtime.StartAsync();
  218.         await Task.Delay(duration);
  219.         await runtime.StopAsync();
  220.     }
  221.     private static async Task PrepareTestState(string configFilePath)
  222.     {
  223.         var message1FilePath = "message1.txt";
  224.  
  225.         await File.WriteAllTextAsync(configFilePath, $"{{\"MessageFilePath\":\"{message1FilePath}\"}}");
  226.         await File.WriteAllTextAsync(message1FilePath, "Hello World!");
  227.     }
  228.     private static IServiceProvider CreateServices(string configFilePath)
  229.     {
  230.         return new ServiceCollection()
  231.             .AddSingleton(new ConfigInfo(configFilePath))
  232.             .AddScoped<CancellationTokenSource>()
  233.             .AddScoped<ICancelTokenSource, CancelTokenSource>()
  234.             .AddScoped<IConfigReader, JsonConfigReader>()
  235.             .AddScoped<IMessageProvider, ConfigMessageProvider>()
  236.             .AddSingleton<IMessageViewer, ConsoleMessageViewer>()
  237.             .AddTransient<IProgramWorker, ProgramWorker>()
  238.             .AddTransient<IProgramRuntime, ProgramRuntime>()
  239.             .AddTransient(_ => new Func<IServiceProvider, IProgramWorker>(s => s.GetRequiredService<IProgramWorker>()))
  240.             .BuildServiceProvider();
  241.     }
  242. }
Advertisement
Add Comment
Please, Sign In to add comment