Add config descriptor and JSON config helpers
Introduces ConfigDescriptor to describe config settings with name, type, and value. Adds DescribeConfig method to Config for structured config introspection. WikiService now generates JSON files for each config class, aiding documentation and tooling.
This commit is contained in:
parent
d46f0457ef
commit
172a0132a2
2 changed files with 106 additions and 11 deletions
|
|
@ -11,6 +11,19 @@ using System.Text.Json;
|
|||
|
||||
namespace SecondBotEvents.Config
|
||||
{
|
||||
public class ConfigDescriptor
|
||||
{
|
||||
public string argname = "";
|
||||
public string argtype = "";
|
||||
public string argvalue = "";
|
||||
|
||||
public ConfigDescriptor(string argname, string argtype, string argvalue)
|
||||
{
|
||||
this.argname = argname;
|
||||
this.argtype = argtype;
|
||||
this.argvalue = argvalue;
|
||||
}
|
||||
}
|
||||
public abstract class Config
|
||||
{
|
||||
protected Dictionary<string, string> mysettings = [];
|
||||
|
|
@ -19,6 +32,51 @@ namespace SecondBotEvents.Config
|
|||
protected bool loaded = false;
|
||||
protected bool tryLoadfromEnv = false;
|
||||
|
||||
public List<ConfigDescriptor> DescribeConfig()
|
||||
{
|
||||
List<ConfigDescriptor> settingsDescribed = [];
|
||||
// Reorder settings: "Enabled" first, "HideStatusOutput" last if present
|
||||
if (settings.Contains("Enabled"))
|
||||
{
|
||||
settings.Remove("Enabled");
|
||||
settings.Insert(0, "Enabled");
|
||||
}
|
||||
if (settings.Contains("HideStatusOutput"))
|
||||
{
|
||||
settings.Remove("HideStatusOutput");
|
||||
settings.Add("HideStatusOutput");
|
||||
}
|
||||
foreach (var setting in settings)
|
||||
{
|
||||
Type configType = this.GetType();
|
||||
string accessor = "Get" + StringExtensions.FirstCharToUpper(setting);
|
||||
MethodInfo method = configType.GetMethod(accessor);
|
||||
|
||||
if (method != null)
|
||||
{
|
||||
// Get the return type
|
||||
Type returnType = method.ReturnType;
|
||||
object value = method.Invoke(this, null);
|
||||
Dictionary<string, string> typeMapping = new()
|
||||
{
|
||||
{ "System.String", "Text" },
|
||||
{ "System.Int32", "Number" },
|
||||
{ "System.UInt64", "Number" }, // everything is a int if you dont check the size
|
||||
{ "System.Boolean", "True|False" },
|
||||
{ "System.Double", "Float" }, // lies :P but SL does not have the concept of double
|
||||
{ "System.String[]", "CSV" } // more lies but we convert them anyway
|
||||
};
|
||||
string typeName = returnType.FullName != null && typeMapping.ContainsKey(returnType.FullName) ? typeMapping[returnType.FullName] : returnType.Name;
|
||||
if(typeName == "CSV")
|
||||
{
|
||||
value = string.Join(",", (string[])value);
|
||||
}
|
||||
settingsDescribed.Add(new ConfigDescriptor(setting, typeName, value.ToString()));
|
||||
}
|
||||
}
|
||||
return settingsDescribed;
|
||||
}
|
||||
|
||||
public Config(bool fromENV, string fromFolder="")
|
||||
{
|
||||
MakeSettings();
|
||||
|
|
@ -56,23 +114,21 @@ namespace SecondBotEvents.Config
|
|||
LoadSettingsFromEnv();
|
||||
return;
|
||||
}
|
||||
LoadSettingsFromFile(fromFolder);
|
||||
if (fromFolder != "")
|
||||
{
|
||||
LoadSettingsFromFile(fromFolder);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void MakeSettingsFile(string fromFolder)
|
||||
{
|
||||
List<ConfigDescriptor> myconfigread = DescribeConfig();
|
||||
|
||||
Dictionary<string, string> saveMe = [];
|
||||
Type thisType = this.GetType();
|
||||
foreach (string setting in settings)
|
||||
foreach (ConfigDescriptor entry in myconfigread)
|
||||
{
|
||||
string reader = "Get"+ StringExtensions.FirstCharToUpper(setting);
|
||||
MethodInfo theMethod = thisType.GetMethod(reader);
|
||||
if (theMethod == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string value = theMethod.Invoke(this, null).ToString();
|
||||
saveMe.Add(setting, value);
|
||||
saveMe.Add(entry.argname, entry.argvalue);
|
||||
}
|
||||
SimpleIO IO = new();
|
||||
IO.ChangeRoot(fromFolder);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@ using System.Reflection;
|
|||
using System.Resources;
|
||||
using System.Security.Policy;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using static log4net.Appender.RollingFileAppender;
|
||||
using static StackExchange.Redis.Role;
|
||||
|
||||
namespace SecondBotEvents
|
||||
{
|
||||
|
|
@ -29,6 +31,43 @@ namespace SecondBotEvents
|
|||
LogFormater.Info("Creating wiki files");
|
||||
IO.ChangeRoot("wiki");
|
||||
makehome();
|
||||
makeJsonConfigHelpers();
|
||||
}
|
||||
|
||||
protected void makeJsonConfigHelpers()
|
||||
{
|
||||
var configNamespace = "SecondBotEvents.Config";
|
||||
var assembly = typeof(SecondBotEvents.Config.Config).Assembly; // Or Assembly.GetExecutingAssembly() if appropriate
|
||||
var excludeNames = new HashSet<string> { "SecondBotEvents.Config.ConfigDescriptor", "SecondBotEvents.Config.Config" };
|
||||
var configClasses = assembly.GetTypes()
|
||||
.Where(t => t.IsClass
|
||||
&& t.Namespace == configNamespace
|
||||
&& !excludeNames.Contains(t.FullName))
|
||||
.ToList();
|
||||
IO.ChangeRoot("json");
|
||||
foreach (var type in configClasses)
|
||||
{
|
||||
try
|
||||
{
|
||||
var worker = Activator.CreateInstance(type, new object[] { false, "" }) as SecondBotEvents.Config.Config;
|
||||
if (worker == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var loaded = worker.DescribeConfig();
|
||||
if (loaded == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string info = JsonSerializer.Serialize(loaded, JsonOptions.UnsafeRelaxed);
|
||||
string name = type.FullName.Replace("SecondBotEvents.Config.", "");
|
||||
IO.WriteFile(name + ".json", info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFormater.Warn("Unable to create json config helper for " + type.FullName + ": " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void makehome()
|
||||
|
|
|
|||
Loading…
Reference in a new issue