Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Microsoft.Extensions.DependencyInjection;
- using Newtonsoft.Json;
- using System;
- using System.IO;
- using System.Threading;
- using System.Threading.Tasks;
- public interface IMessageProvider
- {
- Task<string> GetMessageAsync();
- }
- public interface IMessageViewer
- {
- Task ShowMessageAsync(string message);
- }
- public interface IConfigReader
- {
- Task<IConfig> LoadConfigAsync();
- }
- public interface IConfig
- {
- public string MessageFilePath { get; }
- }
- public interface ICancelTokenSource
- {
- CancellationToken Token { get; }
- }
- public interface IProgramRuntime
- {
- Task StartAsync();
- Task StopAsync();
- }
- public interface IProgramWorker
- {
- Task DoWorkAsync();
- }
- public class ConfigInfo
- {
- public ConfigInfo(string configFilePath)
- {
- ConfigFilePath = configFilePath ?? throw new ArgumentNullException(nameof(configFilePath));
- }
- public string ConfigFilePath { get; }
- }
- public class CancelTokenSource : ICancelTokenSource
- {
- private readonly CancellationTokenSource _realSource;
- public CancelTokenSource(CancellationTokenSource realSource)
- {
- _realSource = realSource ?? throw new ArgumentNullException(nameof(realSource));
- }
- public CancellationToken Token => _realSource.Token;
- }
- public class ConfigMessageProvider : IMessageProvider
- {
- private readonly IConfigReader _configProvider;
- private readonly CancellationToken _cancelToken;
- public ConfigMessageProvider(IConfigReader configProvider, ICancelTokenSource cancelTokenSource)
- {
- if (cancelTokenSource == null)
- throw new ArgumentNullException(nameof(cancelTokenSource));
- _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider));
- _cancelToken = cancelTokenSource.Token;
- }
- public async Task<string> GetMessageAsync()
- {
- var config = await _configProvider.LoadConfigAsync();
- return await File.ReadAllTextAsync(config.MessageFilePath, _cancelToken);
- }
- }
- public class JsonConfigReader : IConfigReader
- {
- private readonly ConfigInfo _configInfo;
- private readonly CancellationToken _cancelToken;
- public JsonConfigReader(ConfigInfo configInfo, ICancelTokenSource cancelTokenSource)
- {
- if (cancelTokenSource == null)
- throw new ArgumentNullException(nameof(cancelTokenSource));
- _configInfo = configInfo ?? throw new ArgumentNullException(nameof(configInfo));
- _cancelToken = cancelTokenSource.Token;
- }
- public async Task<IConfig> LoadConfigAsync()
- {
- var configFilePath = _configInfo.ConfigFilePath;
- var configJson = await File.ReadAllTextAsync(configFilePath, _cancelToken);
- return JsonConvert.DeserializeObject<Config>(configJson);
- }
- private class Config : IConfig
- {
- public string MessageFilePath { get; set; }
- }
- }
- public class ConsoleMessageViewer : IMessageViewer
- {
- public Task ShowMessageAsync(string message)
- {
- Console.WriteLine(message);
- return Task.CompletedTask;
- }
- }
- public class ProgramRuntime : IProgramRuntime, IDisposable
- {
- private readonly Func<IServiceProvider, IProgramWorker> _workerFactory;
- private readonly IServiceScopeFactory _scopeFactory;
- private CancellationTokenSource _cancelTokenSource;
- private Task _runtimeTask;
- public ProgramRuntime(IServiceScopeFactory scopeFactory, Func<IServiceProvider, IProgramWorker> workerFactory)
- {
- _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
- _workerFactory = workerFactory ?? throw new ArgumentNullException(nameof(workerFactory));
- }
- public async Task StartAsync()
- {
- await StopAsync();
- _cancelTokenSource = new CancellationTokenSource();
- _runtimeTask = Task.Factory.StartNew(
- DoWorkLoop,
- _cancelTokenSource.Token,
- TaskCreationOptions.LongRunning,
- TaskScheduler.Default)
- .Unwrap();
- }
- public async Task StopAsync()
- {
- _cancelTokenSource?.Cancel();
- try
- {
- await (_runtimeTask ?? Task.CompletedTask);
- }
- catch (TaskCanceledException) { }
- _cancelTokenSource?.Dispose();
- _runtimeTask?.Dispose();
- }
- private async Task DoWorkLoop()
- {
- while(!_cancelTokenSource.IsCancellationRequested)
- {
- using (var scope = _scopeFactory.CreateScope())
- {
- var worker = _workerFactory(scope.ServiceProvider);
- await worker.DoWorkAsync();
- }
- await Task.Delay(100, _cancelTokenSource.Token);
- }
- }
- public void Dispose()
- {
- _cancelTokenSource?.Dispose();
- _runtimeTask?.Dispose();
- }
- }
- public class ProgramWorker : IProgramWorker
- {
- private readonly IMessageProvider _messageProvider;
- private readonly IMessageViewer _messageViewer;
- public ProgramWorker(IMessageProvider messageProvider, IMessageViewer messageViewer)
- {
- _messageProvider = messageProvider ?? throw new ArgumentNullException(nameof(messageProvider));
- _messageViewer = messageViewer ?? throw new ArgumentNullException(nameof(messageViewer));
- }
- public async Task DoWorkAsync()
- {
- try
- {
- var message = await _messageProvider.GetMessageAsync();
- await _messageViewer.ShowMessageAsync(message);
- }
- catch (Exception ex)
- {
- await _messageViewer.ShowMessageAsync(ex.ToString());
- }
- }
- }
- internal class Program
- {
- private static async Task Main()
- {
- var configFilePath = "config.json";
- await PrepareTestState(configFilePath);
- var services = CreateServices(configFilePath);
- await RunProgram(services, TimeSpan.FromSeconds(10));
- }
- private static async Task RunProgram(IServiceProvider services, TimeSpan duration)
- {
- var runtime = services.GetRequiredService<IProgramRuntime>();
- await runtime.StartAsync();
- await Task.Delay(duration);
- await runtime.StopAsync();
- }
- private static async Task PrepareTestState(string configFilePath)
- {
- var message1FilePath = "message1.txt";
- await File.WriteAllTextAsync(configFilePath, $"{{\"MessageFilePath\":\"{message1FilePath}\"}}");
- await File.WriteAllTextAsync(message1FilePath, "Hello World!");
- }
- private static IServiceProvider CreateServices(string configFilePath)
- {
- return new ServiceCollection()
- .AddSingleton(new ConfigInfo(configFilePath))
- .AddScoped<CancellationTokenSource>()
- .AddScoped<ICancelTokenSource, CancelTokenSource>()
- .AddScoped<IConfigReader, JsonConfigReader>()
- .AddScoped<IMessageProvider, ConfigMessageProvider>()
- .AddSingleton<IMessageViewer, ConsoleMessageViewer>()
- .AddTransient<IProgramWorker, ProgramWorker>()
- .AddTransient<IProgramRuntime, ProgramRuntime>()
- .AddTransient(_ => new Func<IServiceProvider, IProgramWorker>(s => s.GetRequiredService<IProgramWorker>()))
- .BuildServiceProvider();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment