diff --git a/Il2CppInspector.Common/Plugins/API/V100/IPluginOption.cs b/Il2CppInspector.Common/Plugins/API/V100/IPluginOption.cs
index 9df088c..2cc9d8c 100644
--- a/Il2CppInspector.Common/Plugins/API/V100/IPluginOption.cs
+++ b/Il2CppInspector.Common/Plugins/API/V100/IPluginOption.cs
@@ -4,7 +4,9 @@
All rights reserved.
*/
+using System;
using System.Collections.Generic;
+using System.Linq;
namespace Il2CppInspector.PluginAPI.V100
{
@@ -80,8 +82,30 @@ namespace Il2CppInspector.PluginAPI.V100
/// When created, the default value of the option
/// During plugin execution, the current value of the option
///
+ private T _value;
object IPluginOption.Value { get => Value; set => Value = (T) value; }
- public T Value { get; set; }
+ public T Value {
+ get => _value;
+ set {
+ // Perform internal validation
+ InternalValidate(value);
+
+ // Perform optional user-supplied validation
+ Validate?.Invoke(value);
+
+ // Save changes
+ _value = value;
+ }
+ }
+
+ ///
+ /// Optional validation function for the option in addition to basic automatic validation
+ /// Must either throw an exception or return true
+ ///
+ public Func Validate;
+
+ // Internal validation of each option (for internal use only)
+ protected abstract void InternalValidate(T value);
}
///
@@ -103,17 +127,37 @@ namespace Il2CppInspector.PluginAPI.V100
///
/// Option representing a text string
///
- public class PluginOptionText : PluginOption { }
+ public class PluginOptionText : PluginOption
+ {
+ protected sealed override void InternalValidate(string text) {
+ // Don't allow required text to be empty
+ if (Required && string.IsNullOrWhiteSpace(text))
+ throw new ArgumentException("Text cannot be empty");
+ }
+ }
///
/// Option representing a file path
///
- public class PluginOptionFilePath : PluginOption { }
+ public class PluginOptionFilePath : PluginOption
+ {
+ // Don't asllow required path name to be empty
+ protected sealed override void InternalValidate(string path) {
+ if (Required && string.IsNullOrWhiteSpace(path))
+ throw new ArgumentException("Path name is required");
+
+ // Throws an exception if the path is invalid (file or folder may or may not exist)
+ System.IO.Path.GetFullPath(path ?? "");
+ }
+ }
///
/// And option representing boolean true or false (yes/no, on/off etc.)
///
- public class PluginOptionBoolean : PluginOption { }
+ public class PluginOptionBoolean : PluginOption
+ {
+ protected sealed override void InternalValidate(bool value) { }
+ }
///
/// Option representing a number
@@ -131,6 +175,8 @@ namespace Il2CppInspector.PluginAPI.V100
/// The value of the number
///
object IPluginOptionNumber.Value { get => Value; set => Value = (T) value; }
+
+ protected sealed override void InternalValidate(T value) { }
}
///
@@ -150,5 +196,11 @@ namespace Il2CppInspector.PluginAPI.V100
/// List to display the list as a set of grouped radio buttons in the GUI
///
public PluginOptionChoiceStyle Style { get; set; }
+
+ protected sealed override void InternalValidate(T value) {
+ // Allow Choices to be null so that setting Value first on init doesn't throw an exception
+ if (!Choices?.Keys.Contains(value) ?? false)
+ throw new ArgumentException("Specified choice is not one of the available choices");
+ }
}
}
\ No newline at end of file