Code/Util/Math/UnaryOperator.cs
namespace Nodebox.Util.Math;
public abstract class UnaryOperator {
public static Dictionary<Type, UnaryOperator> LazyStore { get; set; } = [];
public static T Get<T>() where T : UnaryOperator, new() {
if (LazyStore.TryGetValue(typeof(T), out var op)) {
return (T)op;
}
var instance = new T();
LazyStore[typeof(T)] = instance;
return instance;
}
public Dictionary<Type, Func<object, object>> Lookup;
public UnaryOperator() {
Lookup = GenerateLookup();
}
public virtual Dictionary<Type, Func<object, object>> GenerateLookup() {
var lookup = BaseLookup;
var seq = TypeLibrary.GetMethodsWithAttribute<ModifierAttribute>().OrderBy(x => x.Method.GetCustomAttribute<OrderAttribute>()?.Value ?? 0);
foreach (var (func, attr) in seq) {
func.Invoke(null, [attr.Type, lookup]);
}
return lookup;
}
public abstract Dictionary<Type, Func<object, object>> BaseLookup { get; }
public object Apply(object a) => Lookup[a.GetType()](a);
public bool IsValid<T>() => Lookup.ContainsKey(typeof(T));
public bool IsValid(Type a) => Lookup.ContainsKey(a);
public bool IsValid(object a) => IsValid(a.GetType());
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ModifierAttribute(Type type) : Attribute {
public Type Type { get; set; } = type;
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class ModifierAttribute<T> : ModifierAttribute {
public ModifierAttribute() : base(typeof(T)) { }
}
}
public static class UnaryOperatorExtensions {
extension<T>(T unaryOperator) where T : UnaryOperator, new() {
public static T Global => UnaryOperator.Get<T>();
}
}