using Qrakhen.Qamp.Core.Values.Objects; using System.Reflection; namespace Qrakhen.Qamp.Core.Values.Native; public class NativeMemberAttribute(string? name = null) : Attribute { public string? Name { get; } = name; } public class NativeMember(string name, MemberInfo info) { public string Name { get; } = name; public MemberInfo MemberInfo { get; } = info; } public class NativeProperty(string name, PropertyInfo info, bool readOnly) : NativeMember(name, info) { public bool ReadOnly { get; } = readOnly; public PropertyInfo PropertyInfo => (MemberInfo as PropertyInfo)!; } public class NativeMethod(string name, MethodInfo info) : NativeMember(name, info) { public MethodInfo MethodInfo => (MemberInfo as MethodInfo)!; } public static class NativeLinker { private static readonly Dictionary> _linked = []; private static Dictionary GetLinkTable() => GetLinkTable(typeof(T)); private static Dictionary GetLinkTable(Type type) { if (!_linked.TryGetValue(type, out Dictionary? table)) { table = Compile(type); } if (table == null) { throw new QampException($"{type.Name} has no native members that could be accessed."); } return table; } private static M GetNativeMember(string name) where M : NativeMember => GetNativeMember(typeof(T), name); private static T GetNativeMember(Type type, string name) { if (GetLinkTable(type).TryGetValue(name, out NativeMember? member)) { if (member is T typedMember) { return typedMember; } } throw new QampException($"{type.Name} has no member {name} that could be accessed."); } public static Value GetProperty(TObj obj, string name) { var property = GetNativeMember(name); return Value.Void; //new Value(property.PropertyInfo.GetValue(obj)); } public static void SetProperty(TObj obj, string name, Value value) { } public static Value CallMember(TObj obj, string name, Value[] args) { var method = GetNativeMember(name); return Value.Void; } private static void Compile(Type type, string method, int argCount) { } private static void Compile(Type type, string member) { } private static Dictionary Compile(Type type) { var members = type.GetMembers(); var table = new Dictionary(); foreach (var member in members) { var attr = member.GetCustomAttribute(); if (attr == null) continue; NativeMember? native = null; if (member is PropertyInfo propertyInfo) { native = new NativeProperty(attr.Name ?? member.Name, propertyInfo, propertyInfo.CanWrite); } if (member is MethodInfo methodInfo) { native = new NativeMethod(attr.Name ?? methodInfo.Name, methodInfo); } if (native == null) throw new Exception("meh."); table[native.Name] = native; } return _linked[type] = table; } } /* 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)); } }*/