Skip to content

Commit a9825d2

Browse files
committed
Configuration: Add option to exclude hidden Fields during serialization
1 parent 9575f39 commit a9825d2

3 files changed

Lines changed: 98 additions & 31 deletions

File tree

LukeBot.Common/Configuration.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ protected ConfigurationBase(string eventName, string configurableName)
143143
FullConfigurableTypeName = configurableName;
144144
}
145145

146-
public abstract string Serialize();
146+
public abstract string Serialize(bool includeHidden = false);
147147
public abstract Dictionary<string, ConfigurationField> GetFields();
148148
public virtual string ToShortString() { return EventName; }
149149
}
@@ -427,10 +427,10 @@ public Configuration()
427427
CollectConfigurationVisibilityAttributes(this);
428428
}
429429

430-
public override string Serialize()
430+
public override string Serialize(bool includeHidden = false)
431431
{
432432
JsonSerializerOptions opts = new();
433-
opts.Converters.Add(new ConfigurationJsonConverter<Configurable>());
433+
opts.Converters.Add(new ConfigurationJsonConverter<Configurable>(includeHidden));
434434

435435
return JsonSerializer.Serialize(this, opts);
436436
}

LukeBot.Common/ConfigurationJsonConverter.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ namespace LukeBot.Common
99
internal class ConfigurationJsonConverter<Configurable>: JsonConverter<Configurable>
1010
where Configurable: Configuration<Configurable>, new()
1111
{
12+
private bool IncludeHidden { get; init; }
13+
14+
public ConfigurationJsonConverter()
15+
: this(false)
16+
{
17+
}
18+
19+
public ConfigurationJsonConverter(bool includeHidden)
20+
{
21+
IncludeHidden = includeHidden;
22+
}
23+
1224
public override bool CanConvert(Type typeToConvert)
1325
{
1426
return typeof(ConfigurationBase).IsAssignableFrom(typeToConvert);
@@ -56,6 +68,8 @@ public sealed override void Write(Utf8JsonWriter writer, Configurable configurat
5668
Dictionary<string, ConfigurationField> fields = configuration.GetFields();
5769
foreach (ConfigurationField field in fields.Values)
5870
{
71+
if (!IncludeHidden && !field.Visible) continue;
72+
5973
// TODO while this prevents writing sub-objects as "separate" objects,
6074
// this also will simply write down every single field inside that object, not just ConfigurationFieldAttribute-ones
6175
// This needs adjusting, most likely some deeper inspection based on the Dictionary above

Tools/LukeBot.Tests/Common/ConfigurationTests.cs

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class ConfigurationTests
2020
// NOTE 2 ELECTRIC BOOGALOO: the ordering matters for Serialize test. Attribute-registered
2121
// members are registered when base constructor is called.
2222

23-
private class EventTestConfiguration
23+
private class DefaultTestConfiguration
2424
{
2525
[JsonInclude]
2626
public bool boolField = true;
@@ -52,7 +52,10 @@ private class EventTestConfiguration
5252
[JsonInclude]
5353
public string FullConfigurableTypeName = typeof(TestConfiguration).FullName;
5454

55-
public EventTestConfiguration()
55+
// non-JsonInclude-d for purpose, hidden fields should be omitted from JSON drop
56+
public int hiddenField = 420;
57+
58+
public DefaultTestConfiguration()
5659
{
5760
}
5861
}
@@ -97,31 +100,35 @@ public string Allowed()
97100
}
98101
}
99102

100-
private static readonly EventTestConfiguration EVENT_TEST_CONFIGURATION = new();
103+
private static readonly DefaultTestConfiguration DEFAULT_TEST_CONFIGURATION = new();
101104

102105
private class TestConfiguration: Configuration<TestConfiguration>
103106
{
104107
[ConfigurationField]
105-
public bool boolField = EVENT_TEST_CONFIGURATION.boolField;
108+
public bool boolField = DEFAULT_TEST_CONFIGURATION.boolField;
106109
[ConfigurationField]
107-
public int intField = EVENT_TEST_CONFIGURATION.intField;
110+
public int intField = DEFAULT_TEST_CONFIGURATION.intField;
108111
[ConfigurationField]
109-
public string stringField = EVENT_TEST_CONFIGURATION.stringField;
112+
public string stringField = DEFAULT_TEST_CONFIGURATION.stringField;
110113
[ConfigurationField]
111-
private int privateIntRegisteredViaAttribute = EVENT_TEST_CONFIGURATION.privateIntRegisteredViaAttribute;
114+
private int privateIntRegisteredViaAttribute = DEFAULT_TEST_CONFIGURATION.privateIntRegisteredViaAttribute;
112115
[ConfigurationRestrictedField<string>(typeof(TestRestrictedFieldValidator))]
113-
public string restrictedField = EVENT_TEST_CONFIGURATION.restrictedField;
114-
[ConfigurationListRestrictedField<int>(new[] {2, 4, 6, 8})]
115-
public int evenSingleDigitsField = EVENT_TEST_CONFIGURATION.evenSingleDigitsField;
116+
public string restrictedField = DEFAULT_TEST_CONFIGURATION.restrictedField;
117+
[ConfigurationListRestrictedField<int>(new[] { 2, 4, 6, 8 })]
118+
public int evenSingleDigitsField = DEFAULT_TEST_CONFIGURATION.evenSingleDigitsField;
116119

117-
public string manuallyRestrictedField = EVENT_TEST_CONFIGURATION.manuallyRestrictedField;
120+
public string manuallyRestrictedField = DEFAULT_TEST_CONFIGURATION.manuallyRestrictedField;
118121

119122
// below field on purpose has no attribute, as we are registering it manually with RegisterField()
120-
public bool boolRegisteredManually = EVENT_TEST_CONFIGURATION.boolRegisteredManually;
121-
private int privateIntRegisteredManually = EVENT_TEST_CONFIGURATION.privateIntRegisteredManually;
123+
public bool boolRegisteredManually = DEFAULT_TEST_CONFIGURATION.boolRegisteredManually;
124+
private int privateIntRegisteredManually = DEFAULT_TEST_CONFIGURATION.privateIntRegisteredManually;
122125

123126
private int privateIntNotRegistered = 0;
124127

128+
[ConfigurationField]
129+
[ConfigurationFieldHidden]
130+
public int hiddenField = DEFAULT_TEST_CONFIGURATION.hiddenField;
131+
125132
public TestConfiguration()
126133
{
127134
RegisterField(nameof(manuallyRestrictedField), () => manuallyRestrictedField, new TestManuallyRestrictedFieldValidator());
@@ -141,6 +148,7 @@ public void CheckFields()
141148
Assert.IsNotNull(Field(nameof(evenSingleDigitsField)));
142149
Assert.IsNotNull(Field(nameof(boolRegisteredManually)));
143150
Assert.IsNotNull(Field(nameof(privateIntRegisteredManually)));
151+
Assert.IsNotNull(Field(nameof(hiddenField)));
144152

145153
// check if accessors exist
146154
Assert.IsNotNull(Accessor<bool>(nameof(boolField)));
@@ -152,6 +160,7 @@ public void CheckFields()
152160
Assert.IsNotNull(Accessor<int>(nameof(evenSingleDigitsField)));
153161
Assert.IsNotNull(Accessor<bool>(nameof(boolRegisteredManually)));
154162
Assert.IsNotNull(Accessor<int>(nameof(privateIntRegisteredManually)));
163+
Assert.IsNotNull(Accessor<int>(nameof(hiddenField)));
155164

156165
// check if some random field does not exist
157166
Assert.ThrowsException<ConfigurationException>(() => Field(nameof(privateIntNotRegistered)));
@@ -172,17 +181,29 @@ public void CheckFields()
172181
Assert.AreEqual(ConfigurationFieldType.Simple, Field(nameof(boolRegisteredManually)).FieldType);
173182
Assert.AreEqual(ConfigurationFieldType.Simple, Field(nameof(privateIntRegisteredManually)).FieldType);
174183

175-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.boolField, boolField);
176-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.intField, intField);
177-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.stringField, stringField);
178-
179-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.restrictedField, restrictedField);
180-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.manuallyRestrictedField, manuallyRestrictedField);
181-
182-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.boolRegisteredManually, boolRegisteredManually);
183-
184-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.privateIntRegisteredManually, privateIntRegisteredManually);
185-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.privateIntRegisteredViaAttribute, privateIntRegisteredViaAttribute);
184+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.boolField, boolField);
185+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.intField, intField);
186+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.stringField, stringField);
187+
188+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.restrictedField, restrictedField);
189+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.manuallyRestrictedField, manuallyRestrictedField);
190+
191+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.boolRegisteredManually, boolRegisteredManually);
192+
193+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.privateIntRegisteredManually, privateIntRegisteredManually);
194+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.privateIntRegisteredViaAttribute, privateIntRegisteredViaAttribute);
195+
196+
// check field default visibility
197+
Assert.IsTrue(Field(nameof(boolField)).Visible);
198+
Assert.IsTrue(Field(nameof(intField)).Visible);
199+
Assert.IsTrue(Field(nameof(stringField)).Visible);
200+
Assert.IsTrue(Field(nameof(privateIntRegisteredViaAttribute)).Visible);
201+
Assert.IsTrue(Field(nameof(restrictedField)).Visible);
202+
Assert.IsTrue(Field(nameof(manuallyRestrictedField)).Visible);
203+
Assert.IsTrue(Field(nameof(evenSingleDigitsField)).Visible);
204+
Assert.IsTrue(Field(nameof(boolRegisteredManually)).Visible);
205+
Assert.IsTrue(Field(nameof(privateIntRegisteredManually)).Visible);
206+
Assert.IsFalse(Field(nameof(hiddenField)).Visible);
186207
}
187208

188209
public void TryRegisterExisting()
@@ -206,6 +227,18 @@ public class MismatchedAttributeAndValidatorType: Configuration<MismatchedAttrib
206227
public int myTypeMatchesButValidatorDoesNot = 420;
207228
}
208229

230+
public class DefaultRestrictedFieldTestConfiguration: Configuration<DefaultRestrictedFieldTestConfiguration>
231+
{
232+
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
233+
public string restrictedSetToSecond = "second";
234+
235+
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
236+
public string restrictedEmpty;
237+
238+
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
239+
public string restrictedBadDefault = "wrong";
240+
}
241+
209242

210243
[TestMethod]
211244
public void Configuration_Register()
@@ -370,19 +403,39 @@ public void Configuration_JsonConverterTest_Serialize()
370403
TestConfiguration conf = new();
371404
conf.CheckFields();
372405

373-
Assert.AreEqual(JsonSerializer.Serialize<EventTestConfiguration>(EVENT_TEST_CONFIGURATION), conf.Serialize());
406+
// default serialization should skip hidden fields
407+
string expected = JsonSerializer.Serialize<DefaultTestConfiguration>(DEFAULT_TEST_CONFIGURATION);
408+
Assert.AreEqual(expected, conf.Serialize());
409+
410+
// we can force Serialize to add hidden fields as well
411+
// do a simple check to see if it will contain those
412+
string serializedWithAllFields = conf.Serialize(true);
413+
Assert.IsTrue(serializedWithAllFields.Contains(nameof(conf.hiddenField)));
374414
}
375415

376416
[TestMethod]
377417
public void Configuration_JsonConverterTest_Deserialize()
378418
{
379-
string serialized = JsonSerializer.Serialize<EventTestConfiguration>(EVENT_TEST_CONFIGURATION);
419+
string serialized = JsonSerializer.Serialize<DefaultTestConfiguration>(DEFAULT_TEST_CONFIGURATION);
380420

381421
TestConfiguration conf = ConfigurationFactory.Deserialize(serialized) as TestConfiguration;
382422
Assert.IsNotNull(conf);
383-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.EventName, conf.EventName);
384-
Assert.AreEqual(EVENT_TEST_CONFIGURATION.FullConfigurableTypeName, conf.FullConfigurableTypeName);
423+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.EventName, conf.EventName);
424+
Assert.AreEqual(DEFAULT_TEST_CONFIGURATION.FullConfigurableTypeName, conf.FullConfigurableTypeName);
385425
conf.CheckFields();
386426
}
427+
428+
[TestMethod]
429+
public void Configuration_RestrictedDefaults()
430+
{
431+
// this should not throw
432+
DefaultRestrictedFieldTestConfiguration conf = new();
433+
434+
// default value that is part of the restriction list should be left alone
435+
Assert.AreEqual("second", conf.restrictedSetToSecond);
436+
437+
// empty
438+
Assert.AreEqual("first", conf.restrictedEmpty);
439+
}
387440
}
388441
}

0 commit comments

Comments
 (0)