199 lines
5.7 KiB
C#
199 lines
5.7 KiB
C#
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<Type, Dictionary<string, NativeMember>> _linked = [];
|
|
|
|
private static Dictionary<string, NativeMember> GetLinkTable<T>() => GetLinkTable(typeof(T));
|
|
|
|
private static Dictionary<string, NativeMember> GetLinkTable(Type type)
|
|
{
|
|
if (!_linked.TryGetValue(type, out Dictionary<string, NativeMember>? 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<T, M>(string name) where M : NativeMember
|
|
=> GetNativeMember<M>(typeof(T), name);
|
|
|
|
private static T GetNativeMember<T>(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>(TObj obj, string name)
|
|
{
|
|
var property = GetNativeMember<TObj, NativeProperty>(name);
|
|
return Value.Void; //new Value(property.PropertyInfo.GetValue(obj));
|
|
}
|
|
|
|
public static void SetProperty<TObj>(TObj obj, string name, Value value)
|
|
{
|
|
|
|
}
|
|
|
|
public static Value CallMember<TObj>(TObj obj, string name, Value[] args)
|
|
{
|
|
var method = GetNativeMember<TObj, NativeMethod>(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<string, NativeMember> Compile(Type type)
|
|
{
|
|
var members = type.GetMembers();
|
|
var table = new Dictionary<string, NativeMember>();
|
|
foreach (var member in members)
|
|
{
|
|
var attr = member.GetCustomAttribute<NativeMemberAttribute>();
|
|
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<Type, Dictionary<string, NativeMember>> _members = [];
|
|
private static readonly Dictionary<Type, Dictionary<string, NativeMember>> _membersStatic = [];
|
|
|
|
private static Dictionary<string, NativeMember> 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));
|
|
}
|
|
}*/ |