using Qrakhen.Qamp.Core.Values.Objects; using System.Reflection; namespace Qrakhen.Qamp.Core.Values.Native; public delegate Value Getter(Obj? self); public delegate void Setter(Obj? self, Value value); public delegate Value Method(Obj? self, Value[] args); public class NativeMember(string name, bool isStatic) { public readonly string Name = name; public readonly bool IsStatic = isStatic; } public class NativeConst(string name, Value value) : NativeMember(name, true) { public readonly Value Value = value; } public class NativeGetter(string name, bool isStatic, Getter getter) : NativeMember(name, isStatic) { public readonly Getter Getter = getter; } public class NativeSetter(string name, bool isStatic, Getter getter, Setter setter) : NativeGetter(name, isStatic, getter) { public readonly Setter Setter = setter; } public class NativeMethod(string name, bool isStatic, Method method) : NativeMember(name, isStatic) { public readonly Method Method = method; } public static class Natives { private static readonly Dictionary> _members = []; private static readonly Dictionary> _membersStatic = []; private static Dictionary Prepare(Type type, string name, bool isStatic) { if (!type.IsAssignableTo(typeof(Obj))) throw new QampException($"Only object types may have native members assigned. The provided type {type} can not have any attached properties or members. Use extensions to handle that type."); var target = isStatic ? _membersStatic : _members; if (!target.ContainsKey(type)) target.Add(type, []); if (target[type].ContainsKey(name)) throw new QampException($"Can not register native {(isStatic ? "static" : "")} member {name} for {type}, that member was already defined."); return target[type]; } public static void Register(Type type, NativeMember member) { var target = Prepare(type, member.Name, member.IsStatic); target[member.Name] = member; } public static void Register(Type type, string name, Value constant) { Register(type, new NativeConst(name, constant)); } public static void Register(Type type, MethodInfo info, Method method) { Register(type, new NativeMethod(info.Name, info.IsStatic, method)); } }