variable changed handlers

This commit is contained in:
alterNERDtive 2022-07-09 00:30:51 +02:00
parent 8b6bc1d16a
commit 3358be75db
2 changed files with 404 additions and 87 deletions

View file

@ -204,5 +204,33 @@ namespace alterNERDtive.Yavapf.Example
Plugin.Log.Notice(
$"This is the example handler for the plugin contexts “^foo.*” and “^.*bar.*”. It has been invoked with '{vaProxy.Context}'.");
}
/// <summary>
/// An example handler for changed <see cref="bool"/> variables. It only
/// applies to the “isDay#” variable.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The GUID of the variable.</param>
[Bool("isDay#")]
public static void DayChanged(string name, bool? from, bool? to, Guid? internalID)
{
Plugin.Log.Notice($"This is the example handler for changed bool variables. It is now {(to ?? false ? "day" : "night")}.");
}
/// <summary>
/// An example handler for changed <see cref="string"/> variables. It
/// doesnt specify a name, so it applies to all of them.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The GUID of the variable.</param>
[String]
public static void StringChanged(string name, string? from, string? to, Guid? internalID)
{
Plugin.Log.Notice($"This is the example handler for changed string variables. '{name}' changed from '{from ?? "Not Set"}' to '{to}'.");
}
}
}

View file

@ -23,6 +23,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using VoiceAttack;
namespace alterNERDtive.Yavapf
@ -57,6 +58,36 @@ namespace alterNERDtive.Yavapf
/// </summary>
protected HandlerList<Action<VoiceAttackInvokeProxyClass>> Contexts { get; set; } = new ();
/// <summary>
/// Gets or sets the Actions to be run when a <see cref="bool"/>
/// variable changed.
/// </summary>
protected HandlerList<Action<string, bool?, bool?, Guid?>> BoolChangedHandlers { get; set; } = new ();
/// <summary>
/// Gets or sets the Actions to be run when a <see cref="DateTime"/>
/// variable changed.
/// </summary>
protected HandlerList<Action<string, DateTime?, DateTime?, Guid?>> DateTimeChangedHandlers { get; set; } = new ();
/// <summary>
/// Gets or sets the Actions to be run when a <see cref="decimal"/>
/// variable changed.
/// </summary>
protected HandlerList<Action<string, decimal?, decimal?, Guid?>> DecimalChangedHandlers { get; set; } = new ();
/// <summary>
/// Gets or sets the Actions to be run when a <see cref="int"/>
/// variable changed.
/// </summary>
protected HandlerList<Action<string, int?, int?, Guid?>> IntChangedHandlers { get; set; } = new ();
/// <summary>
/// Gets or sets the Actions to be run when a <see cref="string"/>
/// variable changed.
/// </summary>
protected HandlerList<Action<string, string?, string?, Guid?>> StringChangedHandlers { get; set; } = new ();
/// <summary>
/// Gets the currently stored VoiceAttackInitProxyClass object which is
/// used to interface with VoiceAttack.
@ -72,46 +103,45 @@ namespace alterNERDtive.Yavapf
/// <summary>
/// Gets or sets the name of the plugin.
/// </summary>
public string? Name { get; set; }
protected string? Name { get; set; }
/// <summary>
/// Gets or sets the current version of the plugin.
/// </summary>
public string? Version { get; set; }
protected string? Version { get; set; }
/// <summary>
/// Gets or sets the description of the plugin.
/// </summary>
public string? Info { get; set; }
protected string? Info { get; set; }
/// <summary>
/// Gets or sets the GUID of the plugin.
/// </summary>
public string? Guid { get; set; }
protected string? Guid { get; set; }
/// <summary>
/// Gets the <see cref="VoiceAttackLog"/> instance the plugin uses to
/// log to the VoiceAttack event log.
///
///
/// You can use this to log your own messages.
/// </summary>
public VoiceAttackLog Log
protected VoiceAttackLog Log
{
get => this.log ??= new VoiceAttackLog(this.Proxy, this.Name);
get => this.log ??= new VoiceAttackLog(this.Proxy, this.Name!);
}
/// <summary>
/// Gets the value of a variable from VoiceAttack.
///
/// Valid varible types are <see cref="bool"/>, <see cref="DateTime"/>,
/// <see cref="decimal"/>, <see cref="int"/>, <see cref="short"/> and
/// <see cref="string"/>.
/// <see cref="decimal"/>, <see cref="int"/> and <see cref="string"/>.
/// </summary>
/// <typeparam name="T">The type of the variable.</typeparam>
/// <param name="name">The name of the variable.</param>
/// <returns>The value of the variable. Can be null.</returns>
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
public T? Get<T>(string name)
protected T? Get<T>(string name)
{
dynamic? ret = typeof(T) switch
{
@ -119,7 +149,6 @@ namespace alterNERDtive.Yavapf
Type dateType when dateType == typeof(DateTime) => this.Proxy.GetDate(name),
Type decType when decType == typeof(decimal) => this.Proxy.GetDecimal(name),
Type intType when intType == typeof(int) => this.Proxy.GetInt(name),
Type shortType when shortType == typeof(short) => this.Proxy.GetSmallInt(name),
Type stringType when stringType == typeof(string) => this.Proxy.GetText(name),
_ => throw new InvalidDataException($"Cannot get variable '{name}': invalid type '{typeof(T).Name}'."),
};
@ -130,14 +159,13 @@ namespace alterNERDtive.Yavapf
/// Sets a variable for use in VoiceAttack.
///
/// Valid varible types are <see cref="bool"/>, <see cref="DateTime"/>,
/// <see cref="decimal"/>, <see cref="int"/>, <see cref="short"/> and
/// <see cref="string"/>.
/// <see cref="decimal"/>, <see cref="int"/> and <see cref="string"/>.
/// </summary>
/// <typeparam name="T">The type of the variable.</typeparam>
/// <param name="name">The name of the variable.</param>
/// <param name="value">The value of the variable. Can not be null.</param>
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
public void Set<T>(string name, T? value)
protected void Set<T>(string name, T? value)
{
if (value == null)
{
@ -159,9 +187,6 @@ namespace alterNERDtive.Yavapf
case int i:
this.Proxy.SetInt(name, i);
break;
case short s:
this.Proxy.SetSmallInt(name, s);
break;
case string s:
this.Proxy.SetText(name, s);
break;
@ -175,13 +200,12 @@ namespace alterNERDtive.Yavapf
/// Unsets a variable for use in VoiceAttack (= sets it to null).
///
/// Valid varible types are <see cref="bool"/>, <see cref="DateTime"/>,
/// <see cref="decimal"/>, <see cref="int"/>, <see cref="short"/> and
/// <see cref="string"/>.
/// <see cref="decimal"/>, <see cref="int"/> and <see cref="string"/>.
/// </summary>
/// <typeparam name="T">The type of the variable.</typeparam>
/// <param name="name">The name of the variable.</param>
/// <exception cref="InvalidDataException">Thrown when the variable is of an invalid type.</exception>
public void Unset<T>(string name)
protected void Unset<T>(string name)
{
switch (typeof(T))
{
@ -197,9 +221,6 @@ namespace alterNERDtive.Yavapf
case Type intType when intType == typeof(int):
this.Proxy.SetInt(name, null);
break;
case Type shortType when shortType == typeof(short):
this.Proxy.SetSmallInt(name, null);
break;
case Type stringType when stringType == typeof(string):
this.Proxy.SetText(name, null);
break;
@ -212,37 +233,37 @@ namespace alterNERDtive.Yavapf
/// The plugins display name, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The display name.</returns>
public string VaDisplayName() => $"{this.Name} v{this.Version}";
protected string VaDisplayName() => $"{this.Name} v{this.Version}";
/// <summary>
/// The plugins description, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The description.</returns>
public string VaDisplayInfo() => this.Info;
protected string VaDisplayInfo() => this.Info!;
/// <summary>
/// The plugins GUID, as required by the VoiceAttack plugin API.
/// </summary>
/// <returns>The GUID.</returns>
public Guid VaId() => new (this.Guid);
protected Guid VaId() => new (this.Guid);
/// <summary>
/// The Init method, as required by the VoiceAttack plugin API.
/// Runs when the plugin is initially loaded.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public void VaInit1(VoiceAttackInitProxyClass vaProxy)
protected void VaInit1(VoiceAttackInitProxyClass vaProxy)
{
this.vaProxy = vaProxy;
this.Set<string>($"{this.Name}.version", this.Version);
this.Log.Debug($"Initializing v{this.Version} …");
this.vaProxy.TextVariableChanged += this.TextVariableChanged;
this.vaProxy.IntegerVariableChanged += this.IntegerVariableChanged;
this.vaProxy.DecimalVariableChanged += this.DecimalVariableChanged;
this.vaProxy.BooleanVariableChanged += this.BooleanVariableChanged;
this.vaProxy.DateVariableChanged += this.DateVariableChanged;
this.vaProxy.DecimalVariableChanged += this.DecimalVariableChanged;
this.vaProxy.IntegerVariableChanged += this.IntegerVariableChanged;
this.vaProxy.TextVariableChanged += this.TextVariableChanged;
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<InitAttribute>().Any()).ToList())
{
@ -264,6 +285,31 @@ namespace alterNERDtive.Yavapf
this.Contexts += (Action<VoiceAttackInvokeProxyClass>)m.CreateDelegate(typeof(Action<VoiceAttackInvokeProxyClass>));
}
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<BoolAttribute>().Any()).ToList())
{
this.BoolChangedHandlers += (Action<string, bool?, bool?, Guid?>)m.CreateDelegate(typeof(Action<string, bool?, bool?, Guid?>));
}
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<DateTimeAttribute>().Any()).ToList())
{
this.DateTimeChangedHandlers += (Action<string, DateTime?, DateTime?, Guid?>)m.CreateDelegate(typeof(Action<string, DateTime?, DateTime?, Guid?>));
}
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<DecimalAttribute>().Any()).ToList())
{
this.DecimalChangedHandlers += (Action<string, decimal?, decimal?, Guid?>)m.CreateDelegate(typeof(Action<string, decimal?, decimal?, Guid?>));
}
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<IntAttribute>().Any()).ToList())
{
this.IntChangedHandlers += (Action<string, int?, int?, Guid?>)m.CreateDelegate(typeof(Action<string, int?, int?, Guid?>));
}
foreach (MethodInfo m in this.GetType().GetMethods().Where(m => m.GetCustomAttributes<StringAttribute>().Any()).ToList())
{
this.StringChangedHandlers += (Action<string, string?, string?, Guid?>)m.CreateDelegate(typeof(Action<string, string?, string?, Guid?>));
}
this.Log.Debug("Running Init handlers …");
this.InitActions?.Invoke(vaProxy);
this.Log.Debug("Finished running Init handlers.");
@ -277,45 +323,39 @@ namespace alterNERDtive.Yavapf
/// Runs whenever a plugin context is invoked.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public void VaInvoke1(VoiceAttackInvokeProxyClass vaProxy)
protected void VaInvoke1(VoiceAttackInvokeProxyClass vaProxy)
{
this.vaProxy = vaProxy;
string context = vaProxy.Context.ToLower();
try
{
bool exists = false;
foreach (Action<VoiceAttackInvokeProxyClass> action in this.Contexts)
{
foreach (ContextAttribute attr in action.Method.GetCustomAttributes<ContextAttribute>())
{
if (attr.Name == context ||
(attr.Name.StartsWith("^") && Regex.Match(context, attr.Name).Success))
{
exists = true;
action.Invoke(vaProxy);
List<Action<VoiceAttackInvokeProxyClass>> actions = this.Contexts.Where(
action => action.Method.GetCustomAttributes<ContextAttribute>().Where(
attr => attr.Name == context ||
(attr.Name.StartsWith("^") && Regex.Match(context, attr.Name).Success))
.Any()).ToList();
// Make sure that we dont run the same Action
// multiple times just because it has e.g. multiple
// matching context regexes.
break;
}
if (actions.Any())
{
foreach (Action<VoiceAttackInvokeProxyClass> action in actions)
{
try
{
action.Invoke(vaProxy);
}
catch (ArgumentNullException e)
{
this.Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while executing plugin context '{context}': {e.Message}");
}
}
if (!exists)
{
this.Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
}
}
catch (ArgumentNullException e)
else
{
this.Log.Error($"Missing parameter '{e.ParamName}' for context '{context}'");
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while executing plugin context '{context}'. ({e.Message})");
this.Log.Error($"Invalid plugin context '{vaProxy.Context}'.");
}
}
@ -324,7 +364,7 @@ namespace alterNERDtive.Yavapf
/// Runs when VoiceAttack is shut down.
/// </summary>
/// <param name="vaProxy">The VoiceAttack proxy object.</param>
public void VaExit1(VoiceAttackProxyClass vaProxy)
protected void VaExit1(VoiceAttackProxyClass vaProxy)
{
this.ExitActions?.Invoke(vaProxy);
}
@ -334,32 +374,157 @@ namespace alterNERDtive.Yavapf
/// Runs whenever all commands are stopped using the “Stop All Commands”
/// button or action.
/// </summary>
public void VaStopCommand()
protected void VaStopCommand()
{
this.StopActions?.Invoke();
}
protected void TextVariableChanged(string name, string from, string to, Guid? internalID = null)
/// <summary>
/// Invoked when a <see cref="bool"/> variable changed.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The internal GUID of the variable.</param>
private void BooleanVariableChanged(string name, bool? from, bool? to, Guid? internalID = null)
{
List<Action<string, bool?, bool?, Guid?>> actions = this.BoolChangedHandlers.Where(
action => action.Method.GetCustomAttributes<BoolAttribute>().Where(
attr => attr.Name == name ||
(attr.Name.StartsWith("^") && Regex.Match(name, attr.Name).Success))
.Any()).ToList();
foreach (Action<string, bool?, bool?, Guid?> action in actions)
{
try
{
action.Invoke(name, from, to, internalID);
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while handling changed bool variable '{name}': {e.Message}");
}
}
}
protected void IntegerVariableChanged(string name, int? from, int? to, Guid? internalID = null)
/// <summary>
/// Invoked when a <see cref="DateTime"/> variable changed.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The internal GUID of the variable.</param>
private void DateVariableChanged(string name, DateTime? from, DateTime? to, Guid? internalID = null)
{
List<Action<string, DateTime?, DateTime?, Guid?>> actions = this.DateTimeChangedHandlers.Where(
action => action.Method.GetCustomAttributes<DateTimeAttribute>().Where(
attr => attr.Name == name ||
(attr.Name.StartsWith("^") && Regex.Match(name, attr.Name).Success))
.Any()).ToList();
foreach (Action<string, DateTime?, DateTime?, Guid?> action in actions)
{
try
{
action.Invoke(name, from, to, internalID);
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while handling changed DateTime variable '{name}': {e.Message}");
}
}
}
protected void DecimalVariableChanged(string name, decimal? from, decimal? to, Guid? internalID = null)
/// <summary>
/// Invoked when a <see cref="decimal"/> variable changed.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The internal GUID of the variable.</param>
private void DecimalVariableChanged(string name, decimal? from, decimal? to, Guid? internalID = null)
{
List<Action<string, decimal?, decimal?, Guid?>> actions = this.DecimalChangedHandlers.Where(
action => action.Method.GetCustomAttributes<DecimalAttribute>().Where(
attr => attr.Name == name ||
(attr.Name.StartsWith("^") && Regex.Match(name, attr.Name).Success))
.Any()).ToList();
foreach (Action<string, decimal?, decimal?, Guid?> action in actions)
{
try
{
action.Invoke(name, from, to, internalID);
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while handling changed decimal variable '{name}': {e.Message}");
}
}
}
protected void BooleanVariableChanged(string name, bool? from, bool? to, Guid? internalID = null)
/// <summary>
/// Invoked when a <see cref="int"/> variable changed.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The internal GUID of the variable.</param>
private void IntegerVariableChanged(string name, int? from, int? to, Guid? internalID = null)
{
List<Action<string, int?, int?, Guid?>> actions = this.IntChangedHandlers.Where(
action => action.Method.GetCustomAttributes<IntAttribute>().Where(
attr => attr.Name == name ||
(attr.Name.StartsWith("^") && Regex.Match(name, attr.Name).Success))
.Any()).ToList();
foreach (Action<string, int?, int?, Guid?> action in actions)
{
try
{
action.Invoke(name, from, to, internalID);
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while handling changed int variable '{name}': {e.Message}");
}
}
}
protected void DateVariableChanged(string name, DateTime? from, DateTime? to, Guid? internalID = null)
/// <summary>
/// Invoked when a <see cref="string"/> variable changed.
/// </summary>
/// <param name="name">The name of the variable.</param>
/// <param name="from">The old value of the variable.</param>
/// <param name="to">The new value of the variable.</param>
/// <param name="internalID">The internal GUID of the variable.</param>
private void TextVariableChanged(string name, string? from, string? to, Guid? internalID = null)
{
List<Action<string, string?, string?, Guid?>> actions = this.StringChangedHandlers.Where(
action => action.Method.GetCustomAttributes<StringAttribute>().Where(
attr => attr.Name == name ||
(attr.Name.StartsWith("^") && Regex.Match(name, attr.Name).Success))
.Any()).ToList();
foreach (Action<string, string?, string?, Guid?> action in actions)
{
try
{
action.Invoke(name, from, to, internalID);
}
catch (Exception e)
{
this.Log.Error($"Unhandled exception while handling changed string variable '{name}': {e.Message}");
}
}
}
public class HandlerList<T> : List<T>
/// <summary>
/// A list of event handlers (Actions). Basically just a list that
/// implements the + and - operators because they look nice.
/// </summary>
/// <typeparam name="T">The type of the list.</typeparam>
protected class HandlerList<T> : List<T>
{
public static HandlerList<T> operator +(HandlerList<T> handlers, T item)
{
@ -374,93 +539,217 @@ namespace alterNERDtive.Yavapf
}
}
/// <summary>
/// Denotes a handler for <see
/// cref="VaInit1(VoiceAttackInitProxyClass)"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
protected class InitAttribute : Attribute
{
}
/// <summary>
/// Denotes a handler for <see
/// cref="VaExit1(VoiceAttackInitProxyClass)"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
protected class ExitAttribute : Attribute
{
}
/// <summary>
/// Denotes a handler for <see cref="VaStopCommand()"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
protected class StopAttribute : Attribute
{
}
/// <summary>
/// Denotes a handler for a plugin contexts.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class ContextAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ContextAttribute"/>
/// class.
/// </summary>
/// <param name="name">The name of or regex for the context.</param>
public ContextAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="ContextAttribute"/>
/// class that will be invoked for all contexts.
/// </summary>
public ContextAttribute()
{
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the context.
/// </summary>
public string Name { get; }
}
/// <summary>
/// Denotes a handler for changed <see cref="bool"/> variables.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class BoolAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="BoolAttribute"/>
/// class.
/// </summary>
/// <param name="name">The name of or regex for the variable.</param>
public BoolAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="BoolAttribute"/>
/// class that will be invoked for all variables.
/// </summary>
public BoolAttribute()
{
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the variable name.
/// </summary>
public string Name { get; }
}
/// <summary>
/// Denotes a handler for changed <see cref="DateTime"/> variables.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class DateTimeAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see
/// cref="DateTimeAttribute"/> class.
/// </summary>
/// <param name="name">The name of or regex for the variable.</param>
public DateTimeAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// Initializes a new instance of the <see
/// cref="DateTimeAttribute"/> class that will be invoked for all
/// variables.
/// </summary>
public DateTimeAttribute()
{
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the variable.
/// </summary>
public string Name { get; }
}
/// <summary>
/// Denotes a handler for changed <see cref="decimal"/> variables.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class DecimalAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="DecimalAttribute"/>
/// class.
/// </summary>
/// <param name="name">The name of or regex for the variable.</param>
public DecimalAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="DecimalAttribute"/>
/// class that will be invoked for all variables.
/// </summary>
public DecimalAttribute()
{
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the variable.
/// </summary>
public string Name { get; }
}
/// <summary>
/// Denotes a handler for changed <see cref="int"/> variables.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class IntAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="IntAttribute"/>
/// class.
/// </summary>
/// <param name="name">The name of or regex for the variable.</param>
public IntAttribute(string name)
{
this.Name = name;
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class ShortAttribute : Attribute
{
public string Name { get; }
public ShortAttribute(string name)
/// <summary>
/// Initializes a new instance of the <see cref="IntAttribute"/>
/// class that will be invoked for all variables.
/// </summary>
public IntAttribute()
{
this.Name = name;
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the variable.
/// </summary>
public string Name { get; }
}
/// <summary>
/// Denotes a handler for changed <see cref="string"/> variables.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
protected class StringAttribute : Attribute
{
public string Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="StringAttribute"/>
/// class.
/// </summary>
/// <param name="name">The name of or regex for the variable.</param>
public StringAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="StringAttribute"/>
/// class that is invoked for all variables.
/// </summary>
public StringAttribute()
{
this.Name = "^.*";
}
/// <summary>
/// Gets the name of or regex for the variable.
/// </summary>
public string Name { get; }
}
}
}