Skip to content

Commit d7348ce

Browse files
committed
ConfigurationField: Validate field on construction
This lets us check whether fields are defaulted to an allowed value, ex. one of the entries in ConfigurationListRestrictedField attribute. Validation failure throws a ConfigurationFieldException.
1 parent a9825d2 commit d7348ce

3 files changed

Lines changed: 33 additions & 5 deletions

File tree

LukeBot.Common/Configuration.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,14 @@ private ConfigurationField AllocateFieldAccessor(object owner, FieldInfo fi, Con
290290
}
291291

292292
// how does this spaghetti work I still have no idea
293-
return Activator.CreateInstance(constructedType, constructorArgs) as ConfigurationField;
293+
try
294+
{
295+
return Activator.CreateInstance(constructedType, constructorArgs) as ConfigurationField;
296+
}
297+
catch (TargetInvocationException e)
298+
{
299+
throw e.InnerException;
300+
}
294301
}
295302

296303
private void RegisterConfigurationFields(object fieldRef, string prefix = "")

LukeBot.Common/ConfigurationField.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
namespace LukeBot.Common
1313
{
1414
// Validator definition
15+
// Note that ConfigurationField constructor WILL run the validator when initializing the accessor.
16+
// This means your object should be defaulted to a value that makes the validation pass.
17+
// If validation during Field construction fails, ConfigurationFieldException will be thrown.
1518
public interface IConfigurationFieldValidator<T>
1619
{
1720
public bool Validate(T input);
@@ -314,6 +317,11 @@ public ConfigurationFieldAccessor(string name, Expression<Func<T>> expression, I
314317
);
315318
Setter = Expression.Lambda<Action<T>>(body, parameter).Compile();
316319
Getter = expression.Compile();
320+
321+
if (!mValidator.Validate(Getter()))
322+
{
323+
throw new ConfigurationFieldException("Default value \"{0}\" that field {1} is set to is invalid", Getter(), Name);
324+
}
317325
}
318326

319327
public void Set(T v) => Setter(v);

Tools/LukeBot.Tests/Common/ConfigurationTests.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,22 @@ public class DefaultRestrictedFieldTestConfiguration: Configuration<DefaultRestr
233233
public string restrictedSetToSecond = "second";
234234

235235
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
236-
public string restrictedEmpty;
236+
public string restrictedSetToFirst = "first";
237237

238+
[ConfigurationListRestrictedField<int>(new int[] { 10, 20, 30 })]
239+
public int restrictedSetTo30 = 30;
240+
}
241+
242+
public class EmptyRestrictedFieldTestConfiguration: Configuration<EmptyRestrictedFieldTestConfiguration>
243+
{
244+
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
245+
public string restrictedEmpty = "";
246+
}
247+
248+
public class WrongDefaultRestrictedFieldTestConfiguration: Configuration<WrongDefaultRestrictedFieldTestConfiguration>
249+
{
238250
[ConfigurationListRestrictedField<string>(new string[] { "first", "second", "third" })]
239-
public string restrictedBadDefault = "wrong";
251+
public string badDefaultRestricted = "wrong";
240252
}
241253

242254

@@ -434,8 +446,9 @@ public void Configuration_RestrictedDefaults()
434446
// default value that is part of the restriction list should be left alone
435447
Assert.AreEqual("second", conf.restrictedSetToSecond);
436448

437-
// empty
438-
Assert.AreEqual("first", conf.restrictedEmpty);
449+
// empty or incorrect fields should be default-assigned to first value on the list
450+
Assert.ThrowsException<ConfigurationFieldException>(() => new EmptyRestrictedFieldTestConfiguration());
451+
Assert.ThrowsException<ConfigurationFieldException>(() => new WrongDefaultRestrictedFieldTestConfiguration());
439452
}
440453
}
441454
}

0 commit comments

Comments
 (0)