From 72d6e1e25469b0b29ac89e895073ef3abebfe18b Mon Sep 17 00:00:00 2001 From: Adam R Grey Date: Wed, 22 Mar 2023 12:21:38 -0400 Subject: [PATCH] this is my favorite style, though always a pain reflect derived types, then instantiate. No registration, just derive :) --- .vscode/launch.json | 3 ++- Configuration.cs | 2 +- Program.cs | 54 +++++++++++++++++++++++++++++++++++-------- Reporters/Dummy.cs | 2 +- Reporters/Reporter.cs | 4 ++-- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2607885..d6f6e45 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,8 @@ "cwd": "${workspaceFolder}", // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console": "internalConsole", - "stopAtEntry": false + "stopAtEntry": false, + "requireExactSource": true }, { "name": ".NET Core Attach", diff --git a/Configuration.cs b/Configuration.cs index 3751fbf..bab2c67 100644 --- a/Configuration.cs +++ b/Configuration.cs @@ -7,7 +7,7 @@ namespace newsletter public List Reporters { get; set; } public class Reporter { - public string Type { get; set; } + public string ReporterClass { get; set; } public string Url { get; set; } public string Username { get; set; } public string Password { get; set; } diff --git a/Program.cs b/Program.cs index ef48af7..a02ab13 100644 --- a/Program.cs +++ b/Program.cs @@ -24,7 +24,7 @@ namespace newsletter static async Task Main(string[] args) { var conf = Configure(); - if(conf == null) return; + if (conf == null) return; var reports = await CollectReports(CollectReporters(conf)); @@ -35,23 +35,23 @@ namespace newsletter static Configuration Configure(string configurationPath = "appsettings.json") { - if(!File.Exists(configurationPath)) + if (!File.Exists(configurationPath)) { Console.Error.WriteLine($"could not find configuration at {configurationPath}! copying sample to that spot."); File.Copy("sample-appsettings.json", configurationPath); //and you know what, if that explodes at the OS level, the OS should give you an error return null; } var fileContents = File.ReadAllText(configurationPath); - if(string.IsNullOrWhiteSpace(fileContents)) + if (string.IsNullOrWhiteSpace(fileContents)) { Console.Error.WriteLine($"configuration file at {configurationPath} was empty! overwriting with sample settings."); File.Copy("sample-appsettings.json", configurationPath, true); return null; } - + var conf = JsonConvert.DeserializeObject(fileContents); - if(conf == null) + if (conf == null) { Console.Error.WriteLine($"configuration file at {configurationPath} was empty! overwriting with sample settings."); File.Copy("sample-appsettings.json", configurationPath, true); @@ -60,17 +60,50 @@ namespace newsletter return conf; } - + static List> CollectReporters(Configuration conf) { - //TODO - throw new NotImplementedException(); + var toReturn = new List>(); + + var reporterTypes = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(domainAssembly => domainAssembly.GetTypes()) + .Where(type => type.IsSubclassOf(typeof(newsletter.Reporters.Reporter)) && !type.IsAbstract) + .ToList(); + var skipPortionInName = "newsletter.Reporters.".Length; + + + foreach(var discoveredConfType in conf.Reporters.Select(r => r.ReporterClass)) + { + Console.WriteLine($"{discoveredConfType} configuration type discovered"); + } + foreach (var reporterType in reporterTypes) + { + Console.WriteLine($"{reporterType.ToString().Substring(skipPortionInName).ToLower()} reporter class discovered"); + Func predicate = r => r.ReporterClass == reporterType.ToString().Substring(skipPortionInName).ToLower(); + if (!conf.Reporters.Any(predicate)) + { + Console.WriteLine($"no configurations for it"); + } + else + { + var configurationsFor = conf.Reporters.Where(predicate); + Console.WriteLine($"{configurationsFor.Count()} configurations for it"); + + foreach (var confFor in configurationsFor) + { + var instance = (newsletter.Reporters.Reporter) Activator.CreateInstance(reporterType); + toReturn.Add(instance.Report(confFor)); + } + } + } + + return toReturn; } - static async Task> CollectReports(List> tasks) + static async Task> CollectReports(List> tasks) { var results = new List(); - foreach(var task in tasks) + foreach (var task in tasks) { var rep = await task; results.Add(rep); @@ -81,6 +114,7 @@ namespace newsletter static HtmlDocument AssembleHTML(IEnumerable reportSections) { //TODO + Console.WriteLine($"assembling {reportSections.Count()} sections"); throw new NotImplementedException(); } diff --git a/Reporters/Dummy.cs b/Reporters/Dummy.cs index a68588a..389fb6c 100644 --- a/Reporters/Dummy.cs +++ b/Reporters/Dummy.cs @@ -6,7 +6,7 @@ namespace newsletter.Reporters public class Dummy : Reporter { #pragma warning disable CS1998 - public async Task Report(Configuration.Reporter config) + public override async Task Report(Configuration.Reporter config) { return new Report() { diff --git a/Reporters/Reporter.cs b/Reporters/Reporter.cs index 412ca4b..0fea2d6 100644 --- a/Reporters/Reporter.cs +++ b/Reporters/Reporter.cs @@ -2,8 +2,8 @@ using System.Threading.Tasks; namespace newsletter.Reporters { - public interface Reporter + public abstract class Reporter { - Task Report(Configuration.Reporter config); + public abstract Task Report(Configuration.Reporter config); } } \ No newline at end of file