Skip to content

Commit 56a81cd

Browse files
committed
Config rework part 2
1 parent c5b8de1 commit 56a81cd

File tree

8 files changed

+309
-248
lines changed

8 files changed

+309
-248
lines changed
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.Linq;
6+
using System.Reflection;
7+
using Novus.Utilities;
8+
using SimpleCore.Utilities;
9+
using SmartImage.Engines;
10+
using SmartImage.Utilities;
11+
12+
namespace SmartImage.Core
13+
{
14+
/// <summary>
15+
/// Utilities for <see cref="SearchConfig" />, <see cref="ConfigComponentAttribute" />
16+
/// </summary>
17+
internal static class ConfigComponents
18+
{
19+
/*
20+
* Handles config components (properties or fields).
21+
*
22+
* A config component is a setting (i.e. field, parameter, etc) within the config.
23+
*
24+
* mname - Member name
25+
* id - Map name (Id)
26+
*/
27+
28+
29+
/// <summary>
30+
/// Update all fields annotated with <see cref="ConfigComponentAttribute" /> using <paramref name="obj" />.
31+
/// </summary>
32+
/// <param name="obj">Object</param>
33+
/// <param name="cfg">Map of values</param>
34+
internal static void UpdateFields(object obj, IDictionary<string, string> cfg)
35+
{
36+
var tuples = obj.GetType().GetAnnotated<ConfigComponentAttribute>();
37+
38+
foreach (var (_, member) in tuples) {
39+
string memberName = member.Name;
40+
41+
string? valStr = ReadComponentMapValue<object>(obj, cfg, memberName).ToString();
42+
43+
var fi = member.GetBackingField();
44+
45+
var val = ParseComponentValue(valStr, fi.FieldType);
46+
47+
fi.SetValue(obj, val);
48+
}
49+
}
50+
51+
/// <summary>
52+
/// Get all members annotated with <see cref="ConfigComponentAttribute" /> in <paramref name="obj" />.
53+
/// </summary>
54+
internal static (ConfigComponentAttribute Attribute, MemberInfo Member)[] GetMembers(object obj)
55+
{
56+
var tuples = obj.GetType().GetAnnotated<ConfigComponentAttribute>();
57+
58+
return tuples.Select(y => (y.Attribute, y.Member)).ToArray();
59+
}
60+
61+
/// <summary>
62+
/// Get all fields annotated with <see cref="ConfigComponentAttribute" /> in <paramref name="obj" />.
63+
/// </summary>
64+
internal static (ConfigComponentAttribute Attribute, FieldInfo Field)[] GetFields(object obj)
65+
{
66+
var tuples = GetMembers(obj);
67+
68+
return tuples.Select(y => (y.Attribute, y.Member.GetBackingField())).ToArray();
69+
}
70+
71+
72+
/// <summary>
73+
/// Get field of name <paramref name="mname" /> annotated with <see cref="ConfigComponentAttribute" /> in
74+
/// <paramref name="obj" />.
75+
/// </summary>
76+
internal static (ConfigComponentAttribute Attribute, FieldInfo Field) GetField(object obj, string mname)
77+
{
78+
var t = obj.GetType();
79+
var field = t.GetFieldAuto(mname);
80+
81+
var attr = field.GetCustomAttribute<ConfigComponentAttribute>();
82+
83+
return (attr, field);
84+
}
85+
86+
/// <summary>
87+
/// Converts all members annotated with <see cref="ConfigComponentAttribute" /> in <paramref name="obj" /> to a
88+
/// <see cref="Dictionary{TKey,TValue}" />.
89+
/// </summary>
90+
internal static IDictionary<string, string> ConvertComponentsToMap(object obj)
91+
{
92+
var cfgFields = GetFields(obj);
93+
94+
var keyValuePairs = cfgFields.Select(f =>
95+
new KeyValuePair<string, string>(f.Attribute.Id, f.Field.GetValue(obj).ToString()));
96+
97+
return new Dictionary<string, string>(keyValuePairs);
98+
}
99+
100+
101+
internal static void WriteComponentsToFile(object obj, string dest) => Collections.WriteDictionary(ConvertComponentsToMap(obj), dest);
102+
103+
104+
internal static T ReadComponentMapValue<T>(object obj, IDictionary<string, string> cfg, string mname)
105+
{
106+
var (attr, field) = GetField(obj, mname);
107+
108+
var defaultValue = (T) attr.DefaultValue;
109+
bool setDefaultIfNull = attr.SetDefaultIfNull;
110+
string name = attr.Id;
111+
112+
113+
var v = ReadComponentMapValue(cfg, name, setDefaultIfNull, defaultValue);
114+
Debug.WriteLine($"{v} -> {name} {field.Name}");
115+
return v;
116+
}
117+
118+
internal static object ParseComponentValue(string rawValue, Type t)
119+
{
120+
if (t.IsEnum) {
121+
Enum.TryParse(t, rawValue, out var e);
122+
return e;
123+
}
124+
125+
if (t == typeof(bool)) {
126+
Boolean.TryParse(rawValue, out bool b);
127+
return b;
128+
}
129+
130+
return rawValue;
131+
}
132+
133+
internal static T ParseComponentValue<T>(string rawValue) =>
134+
(T) ParseComponentValue(rawValue, typeof(T));
135+
136+
137+
private static void AddToComponentMap<T>(IDictionary<string, string> cfg, string id, T value)
138+
{
139+
string? valStr = value.ToString();
140+
141+
if (!cfg.ContainsKey(id)) {
142+
cfg.Add(id, valStr);
143+
}
144+
else {
145+
cfg[id] = valStr;
146+
}
147+
}
148+
149+
/// <summary>
150+
/// Reset all members annotated with <see cref="ConfigComponentAttribute" /> within <paramref name="obj" /> to their
151+
/// respective <see cref="ConfigComponentAttribute.DefaultValue" />.
152+
/// </summary>
153+
internal static void ResetComponents(object obj)
154+
{
155+
var tuples = GetFields(obj);
156+
157+
foreach (var (attr, field) in tuples) {
158+
var dv = attr.DefaultValue;
159+
field.SetValue(obj, dv);
160+
161+
Debug.WriteLine($"Reset {dv} -> {field.Name}");
162+
}
163+
}
164+
165+
/// <summary>
166+
/// Reset config component with member name <paramref name="mname" /> to its
167+
/// <seealso cref="ConfigComponentAttribute.DefaultValue" />.
168+
/// </summary>
169+
internal static void ResetComponent(object obj, string mname)
170+
{
171+
var (attr, field) = GetField(obj, mname);
172+
173+
var dv = attr.DefaultValue;
174+
175+
field.SetValue(obj, dv);
176+
}
177+
178+
179+
internal static T ReadComponentMapValue<T>(IDictionary<string, string> cfg, string id,
180+
bool setDefaultIfNull = false, T defaultValue = default)
181+
{
182+
183+
if (!cfg.ContainsKey(id)) {
184+
cfg.Add(id, String.Empty);
185+
}
186+
187+
string rawValue = cfg[id];
188+
189+
if (setDefaultIfNull && String.IsNullOrWhiteSpace(rawValue)) {
190+
AddToComponentMap(cfg, id, defaultValue.ToString());
191+
rawValue = ReadComponentMapValue<string>(cfg, id);
192+
}
193+
194+
var parse = ParseComponentValue<T>(rawValue);
195+
return parse;
196+
}
197+
198+
199+
internal static void ReadComponentFromArgument(object obj,IEnumerator<string> argEnumerator)
200+
{
201+
var argName = argEnumerator.Current;
202+
203+
var x = GetMembers(obj);
204+
205+
var correspondingComponent = x.FirstOrDefault(y => y.Attribute.ArgumentName == argName);
206+
207+
if (correspondingComponent == default) {
208+
return;
209+
}
210+
211+
argEnumerator.MoveNext();
212+
213+
string argValue2 = argEnumerator.Current;
214+
var bf = correspondingComponent.Member.GetBackingField();
215+
216+
var value = ConfigComponents.ParseComponentValue(argValue2, bf.FieldType);
217+
218+
bf.SetValue(obj, value);
219+
}
220+
}
221+
}

SmartImage/Core/ConfigUtil.cs

Lines changed: 0 additions & 12 deletions
This file was deleted.

SmartImage/Core/Integration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ internal static void ResetIntegrations()
129129
{
130130

131131
SearchConfig.Config.Reset();
132-
SearchConfig.Config.WriteToFile();
132+
SearchConfig.Config.SaveFile();
133133

134134
// Computer\HKEY_CLASSES_ROOT\*\shell\SmartImage
135135

SmartImage/Core/Interface.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ internal static NConsoleInterface MainMenu
202202
Color = ColorConfig,
203203
Function = () =>
204204
{
205-
SearchConfig.Config.WriteToFile();
205+
SearchConfig.Config.SaveFile();
206206

207207
NConsoleIO.WaitForSecond();
208208
return null;

0 commit comments

Comments
 (0)