Support implicit and explicit casting
This commit is contained in:
parent
c1ed9b1eb6
commit
d36d091d28
|
@ -1,133 +1,52 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.UserData;
|
||||
|
||||
namespace PorygonSharp.ScriptType
|
||||
{
|
||||
internal static class ScriptType
|
||||
public class ScriptType
|
||||
{
|
||||
internal static IntPtr? GetScriptType(Type t)
|
||||
private readonly IntPtr _ptr;
|
||||
|
||||
public ScriptType(IntPtr ptr)
|
||||
{
|
||||
if (t.IsEnum && !t.IsGenericParameter)
|
||||
{
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
return CreateNumericScriptType(true, false);
|
||||
}
|
||||
var typeCode = Type.GetTypeCode(t);
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
return CreateScriptType(TypeClass.Bool);
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
return CreateNumericScriptType(true, false);
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Single:
|
||||
return CreateNumericScriptType(true, true);
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
return CreateStringScriptType(false, 0);
|
||||
case TypeCode.Object:
|
||||
if (t == typeof(void))
|
||||
{
|
||||
return CreateScriptType(TypeClass.Nil);
|
||||
}
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
{
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
}
|
||||
if (typeof(IList).IsAssignableFrom(t))
|
||||
{
|
||||
return CreateUserDataListType(t);
|
||||
}
|
||||
if (typeof(IDictionary).IsAssignableFrom(t))
|
||||
{
|
||||
return CreateUserDataDictionaryType(t);
|
||||
_ptr = ptr;
|
||||
}
|
||||
|
||||
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
||||
if (attr != null)
|
||||
public TypeClass GetTypeClass()
|
||||
{
|
||||
UserDataHandler.RegisterType(attr.Identifier, t);
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
return GetTypeClass(_ptr);
|
||||
}
|
||||
return null;
|
||||
|
||||
public uint GetUserDataType()
|
||||
{
|
||||
return GetScriptTypeUserData(_ptr);
|
||||
}
|
||||
|
||||
internal Type ResolveType()
|
||||
{
|
||||
var c = GetTypeClass();
|
||||
switch (c)
|
||||
{
|
||||
case TypeClass.Number: return typeof(long);
|
||||
case TypeClass.Bool: return typeof(bool);
|
||||
case TypeClass.String: return typeof(string);
|
||||
case TypeClass.UserData:
|
||||
var id = GetUserDataType();
|
||||
var t = UserDataHandler.ReverseLookup[id];
|
||||
return t.Type;
|
||||
default:
|
||||
return null;
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr? GetFunctionScriptType(MethodInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
var returnType = GetScriptType(info.ReturnType);
|
||||
if (!returnType.HasValue)
|
||||
return null;
|
||||
var parameters = info.GetParameters();
|
||||
var parameterFuncs = new IntPtr[parameters.Length];
|
||||
for (var index = 0; index < parameters.Length; index++)
|
||||
{
|
||||
var parameter = parameters[index];
|
||||
var parameterType = GetScriptType(parameter.ParameterType);
|
||||
if (!parameterType.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
parameterFuncs[index] = parameterType.Value;
|
||||
}
|
||||
|
||||
return CreateUserDataFunctionScriptType(returnType.Value, parameterFuncs, parameters.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private static IntPtr? CreateUserDataListType(Type t)
|
||||
{
|
||||
var keyType = CreateNumericScriptType(true, false);
|
||||
var valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
|
||||
var valueType = GetScriptType(valType);
|
||||
if (valueType.HasValue)
|
||||
return CreateCollectionType(keyType, valueType.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IntPtr? CreateUserDataDictionaryType(Type t)
|
||||
{
|
||||
var keyType = GetScriptType(t.GenericTypeArguments[0]);
|
||||
var valueType = GetScriptType(t.GenericTypeArguments[1]);
|
||||
if (keyType.HasValue && valueType.HasValue)
|
||||
return CreateCollectionType(keyType.Value, valueType.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateScriptType(TypeClass t);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateNumericScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr CreateNumericScriptType(bool isAware, bool isFloat);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateStringScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateStringScriptType(bool knownAtBind, uint hash);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateUserDataFunctionScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateUserDataFunctionScriptType(IntPtr returnType, IntPtr[] parameters, int parameterCount);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateCollectionType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateCollectionType(IntPtr keyType, IntPtr valueType);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "GetTypeClass", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern TypeClass GetTypeClass(IntPtr t);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "GetScriptTypeUserData", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern uint GetScriptTypeUserData(IntPtr t);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.UserData;
|
||||
|
||||
namespace PorygonSharp.ScriptType
|
||||
{
|
||||
internal static class ScriptTypeHandler
|
||||
{
|
||||
internal static IntPtr? GetScriptType(Type t)
|
||||
{
|
||||
if (t.IsEnum && !t.IsGenericParameter)
|
||||
{
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
return CreateNumericScriptType(true, false);
|
||||
}
|
||||
var typeCode = Type.GetTypeCode(t);
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
return CreateScriptType(TypeClass.Bool);
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
return CreateNumericScriptType(true, false);
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Single:
|
||||
return CreateNumericScriptType(true, true);
|
||||
case TypeCode.Char:
|
||||
case TypeCode.String:
|
||||
return CreateStringScriptType(false, 0);
|
||||
case TypeCode.Object:
|
||||
if (t == typeof(void))
|
||||
{
|
||||
return CreateScriptType(TypeClass.Nil);
|
||||
}
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
{
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
}
|
||||
if (typeof(IList).IsAssignableFrom(t))
|
||||
{
|
||||
return CreateUserDataListType(t);
|
||||
}
|
||||
if (typeof(IDictionary).IsAssignableFrom(t))
|
||||
{
|
||||
return CreateUserDataDictionaryType(t);
|
||||
}
|
||||
|
||||
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
||||
if (attr != null)
|
||||
{
|
||||
UserDataHandler.RegisterType(attr.Identifier, t);
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
}
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr? GetFunctionScriptType(MethodInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
var returnType = GetScriptType(info.ReturnType);
|
||||
if (!returnType.HasValue)
|
||||
return null;
|
||||
var parameters = info.GetParameters();
|
||||
var parameterFuncs = new IntPtr[parameters.Length];
|
||||
for (var index = 0; index < parameters.Length; index++)
|
||||
{
|
||||
var parameter = parameters[index];
|
||||
var parameterType = GetScriptType(parameter.ParameterType);
|
||||
if (!parameterType.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
parameterFuncs[index] = parameterType.Value;
|
||||
}
|
||||
|
||||
return CreateUserDataFunctionScriptType(returnType.Value, parameterFuncs, parameters.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private static IntPtr? CreateUserDataListType(Type t)
|
||||
{
|
||||
var keyType = CreateNumericScriptType(true, false);
|
||||
var valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
|
||||
var valueType = GetScriptType(valType);
|
||||
if (valueType.HasValue)
|
||||
return CreateCollectionType(keyType, valueType.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IntPtr? CreateUserDataDictionaryType(Type t)
|
||||
{
|
||||
var keyType = GetScriptType(t.GenericTypeArguments[0]);
|
||||
var valueType = GetScriptType(t.GenericTypeArguments[1]);
|
||||
if (keyType.HasValue && valueType.HasValue)
|
||||
return CreateCollectionType(keyType.Value, valueType.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateScriptType(TypeClass t);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateNumericScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr CreateNumericScriptType(bool isAware, bool isFloat);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateStringScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateStringScriptType(bool knownAtBind, uint hash);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateUserDataFunctionScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateUserDataFunctionScriptType(IntPtr returnType, IntPtr[] parameters, int parameterCount);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateCollectionType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateCollectionType(IntPtr keyType, IntPtr valueType);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.HelperLibraries;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp
|
||||
|
@ -10,7 +11,7 @@ namespace PorygonSharp
|
|||
public static void RegisterStaticVariable(string name, object o)
|
||||
{
|
||||
var type = o.GetType();
|
||||
var scriptType = ScriptType.ScriptType.GetScriptType(type);
|
||||
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(type);
|
||||
var hash = name.ScriptHash();
|
||||
var value = EvalValueCreator.CreateValue(o);
|
||||
if (!scriptType.HasValue)
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.UserData
|
||||
{
|
||||
|
@ -6,10 +11,155 @@ namespace PorygonSharp.UserData
|
|||
{
|
||||
public readonly Dictionary<uint, UserDataField> Fields = new Dictionary<uint, UserDataField>();
|
||||
public uint Id { get; }
|
||||
public Type Type { get; }
|
||||
private readonly Dictionary<Type, MethodInfo> _implicitCasts;
|
||||
private readonly Dictionary<Type, MethodInfo> _explicitCasts;
|
||||
|
||||
public UserData(uint id)
|
||||
private delegate bool IsCastableDelegate(IntPtr scriptType, bool isExplicit);
|
||||
private delegate IntPtr CastDelegate(IntPtr obj, IntPtr scriptType);
|
||||
|
||||
// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
|
||||
private readonly IsCastableDelegate _isCastableFunc;
|
||||
private readonly CastDelegate _castFunc;
|
||||
// ReSharper restore PrivateFieldCanBeConvertedToLocalVariable
|
||||
|
||||
private const BindingFlags BindingFlags = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance |
|
||||
System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Static;
|
||||
|
||||
public UserData(uint id, Type type)
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
|
||||
_implicitCasts = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||
.Where(mi => string.Equals(mi.Name, "op_Implicit"))
|
||||
.ToDictionary(x => x.ReturnType, x => x);
|
||||
_explicitCasts = type.GetMethods(BindingFlags.Public | BindingFlags.Static)
|
||||
.Where(mi => string.Equals(mi.Name, "op_Explicit"))
|
||||
.ToDictionary(x => x.ReturnType, x => x);
|
||||
|
||||
_isCastableFunc = IsCastable;
|
||||
_castFunc = Cast;
|
||||
|
||||
SetIsCastableFunc(id, Marshal.GetFunctionPointerForDelegate(_isCastableFunc));
|
||||
SetCastFunc(id, Marshal.GetFunctionPointerForDelegate(_castFunc));
|
||||
}
|
||||
|
||||
internal void RegisterFields()
|
||||
{
|
||||
var fields = Type.GetFields(BindingFlags);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
RegisterField(field);
|
||||
}
|
||||
|
||||
var properties = Type.GetProperties(BindingFlags);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
RegisterProperty(property);
|
||||
}
|
||||
|
||||
var methods = Type.GetMethods(BindingFlags);
|
||||
foreach (var method in methods)
|
||||
{
|
||||
RegisterFunction(method);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterField(FieldInfo field)
|
||||
{
|
||||
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(field.FieldType);
|
||||
if (!scriptType.HasValue)
|
||||
return;
|
||||
var fieldName = field.Name.ScriptHash();
|
||||
if (Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(field);
|
||||
var userDataField = CreateUserDataField(scriptType.Value, fieldData.GetGetterPointer(),
|
||||
fieldData.GetSetterPointer());
|
||||
|
||||
RegisterUserDataField(Id, fieldName, userDataField);
|
||||
Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private void RegisterProperty(PropertyInfo property)
|
||||
{
|
||||
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(property.PropertyType);
|
||||
if (!scriptType.HasValue)
|
||||
return;
|
||||
var fieldName = property.Name.ScriptHash();
|
||||
if (Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(property);
|
||||
var userDataField = CreateUserDataField(scriptType.Value, fieldData.GetGetterPointer(),
|
||||
fieldData.GetSetterPointer());
|
||||
|
||||
RegisterUserDataField(Id, fieldName, userDataField);
|
||||
Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private void RegisterFunction(MethodInfo method)
|
||||
{
|
||||
var type = ScriptType.ScriptTypeHandler.GetFunctionScriptType(method);
|
||||
if (type == IntPtr.Zero || !type.HasValue)
|
||||
return;
|
||||
var fieldName = method.Name.ScriptHash();
|
||||
if (Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(method);
|
||||
var userDataField = CreateUserDataField(type.Value, fieldData.GetGetterPointer(), IntPtr.Zero);
|
||||
|
||||
RegisterUserDataField(Id, fieldName, userDataField);
|
||||
Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private bool IsCastable(IntPtr scriptTypePtr, bool isExplicit)
|
||||
{
|
||||
var scriptType = new ScriptType.ScriptType(scriptTypePtr);
|
||||
var expectedType = scriptType.ResolveType();
|
||||
if (expectedType.IsAssignableFrom(Type))
|
||||
return true;
|
||||
if (_implicitCasts.ContainsKey(expectedType))
|
||||
return true;
|
||||
if (isExplicit && _explicitCasts.ContainsKey(expectedType))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private IntPtr Cast(IntPtr objPtr, IntPtr typePtr)
|
||||
{
|
||||
var scriptType = new ScriptType.ScriptType(typePtr);
|
||||
var expectedType = scriptType.ResolveType();
|
||||
var obj = GCHandle.FromIntPtr(objPtr).Target;
|
||||
var objType = obj.GetType();
|
||||
if (expectedType.IsAssignableFrom(objType))
|
||||
return objPtr;
|
||||
if (_implicitCasts.TryGetValue(expectedType, out var func))
|
||||
{
|
||||
var castVal = func.Invoke(null, new[] {obj});
|
||||
var handle = GCHandle.Alloc(castVal, GCHandleType.WeakTrackResurrection);
|
||||
return GCHandle.ToIntPtr(handle);
|
||||
}
|
||||
if (_explicitCasts.TryGetValue(expectedType, out func))
|
||||
{
|
||||
var castVal = func.Invoke(null, new[] {obj});
|
||||
var handle = GCHandle.Alloc(castVal, GCHandleType.WeakTrackResurrection);
|
||||
return GCHandle.ToIntPtr(handle);
|
||||
}
|
||||
throw new Exception("Invalid cast kind");
|
||||
}
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "RegisterUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern void RegisterUserDataField(uint hashId, uint fieldId, IntPtr field);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr CreateUserDataField(IntPtr type, IntPtr getter, IntPtr setter);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "SetIsCastableFunc", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void SetIsCastableFunc(uint id, IntPtr isCastableFunc);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "SetCastFunc", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void SetCastFunc(uint id, IntPtr castFunc);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.Attributes;
|
||||
|
@ -13,7 +11,7 @@ namespace PorygonSharp.UserData
|
|||
public static class UserDataHandler
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, UserData> UserDataLookup = new ConcurrentDictionary<Type, UserData>();
|
||||
private static readonly ConcurrentDictionary<uint, UserData> ReverseLookup = new ConcurrentDictionary<uint, UserData>();
|
||||
internal static readonly ConcurrentDictionary<uint, UserData> ReverseLookup = new ConcurrentDictionary<uint, UserData>();
|
||||
|
||||
|
||||
public static void RegisterAssembly(Assembly assembly)
|
||||
|
@ -43,29 +41,10 @@ namespace PorygonSharp.UserData
|
|||
if (UserDataLookup.ContainsKey(type))
|
||||
return;
|
||||
RegisterUserDataType(hash);
|
||||
var ud = new UserData(hash);
|
||||
var ud = new UserData(hash, type);
|
||||
UserDataLookup.TryAdd(type, ud);
|
||||
ReverseLookup.TryAdd(hash, ud);
|
||||
}
|
||||
|
||||
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance |
|
||||
BindingFlags.FlattenHierarchy | BindingFlags.Static;
|
||||
var fields = type.GetFields(bindingFlags);
|
||||
foreach (var field in fields)
|
||||
{
|
||||
RegisterField(field, hash);
|
||||
}
|
||||
|
||||
var properties = type.GetProperties(bindingFlags);
|
||||
foreach (var property in properties)
|
||||
{
|
||||
RegisterProperty(property, hash);
|
||||
}
|
||||
|
||||
var methods = type.GetMethods(bindingFlags);
|
||||
foreach (var method in methods)
|
||||
{
|
||||
RegisterFunction(method, hash);
|
||||
ud.RegisterFields();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +56,7 @@ namespace PorygonSharp.UserData
|
|||
if (UserDataLookup.ContainsKey(type))
|
||||
return;
|
||||
RegisterUserDataType(hash);
|
||||
var ud = new UserData(hash);
|
||||
var ud = new UserData(hash, type);
|
||||
UserDataLookup.TryAdd(type, ud);
|
||||
ReverseLookup.TryAdd(hash, ud);
|
||||
}
|
||||
|
@ -88,67 +67,14 @@ namespace PorygonSharp.UserData
|
|||
var fieldData = new UserDataField(getter, null);
|
||||
var valueName = Enum.GetName(type, value);
|
||||
var fieldName = valueName.ScriptHash();
|
||||
var t = ScriptType.ScriptType.CreateNumericScriptType(true, false);
|
||||
RegisterUserDataField(hash, fieldName,
|
||||
CreateUserDataField(t, fieldData.GetGetterPointer(), IntPtr.Zero));
|
||||
var t = ScriptType.ScriptTypeHandler.CreateNumericScriptType(true, false);
|
||||
UserData.RegisterUserDataField(hash, fieldName,
|
||||
UserData.CreateUserDataField(t, fieldData.GetGetterPointer(), IntPtr.Zero));
|
||||
ReverseLookup[hash].Fields[fieldName] = fieldData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void RegisterField(FieldInfo field, uint typeHash)
|
||||
{
|
||||
var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType);
|
||||
if (!scriptType.HasValue)
|
||||
return;
|
||||
if (!ReverseLookup.TryGetValue(typeHash, out var userData))
|
||||
return;
|
||||
var fieldName = field.Name.ScriptHash();
|
||||
if (userData.Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(field);
|
||||
var userDataField = CreateUserDataField(scriptType.Value, fieldData.GetGetterPointer(),
|
||||
fieldData.GetSetterPointer());
|
||||
|
||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||
userData.Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private static void RegisterProperty(PropertyInfo property, uint typeHash)
|
||||
{
|
||||
var scriptType = ScriptType.ScriptType.GetScriptType(property.PropertyType);
|
||||
if (!scriptType.HasValue)
|
||||
return;
|
||||
if (!ReverseLookup.TryGetValue(typeHash, out var userData))
|
||||
return;
|
||||
var fieldName = property.Name.ScriptHash();
|
||||
if (userData.Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(property);
|
||||
var userDataField = CreateUserDataField(scriptType.Value, fieldData.GetGetterPointer(),
|
||||
fieldData.GetSetterPointer());
|
||||
|
||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||
userData.Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private static void RegisterFunction(MethodInfo method, uint typeHash)
|
||||
{
|
||||
|
||||
var type = ScriptType.ScriptType.GetFunctionScriptType(method);
|
||||
if (type == IntPtr.Zero || !type.HasValue)
|
||||
return;
|
||||
if (!ReverseLookup.TryGetValue(typeHash, out var userData))
|
||||
return;
|
||||
var fieldName = method.Name.ScriptHash();
|
||||
if (userData.Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(method);
|
||||
var userDataField = CreateUserDataField(type.Value, fieldData.GetGetterPointer(), IntPtr.Zero);
|
||||
|
||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||
userData.Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
public static uint GetTypeId(Type t)
|
||||
{
|
||||
|
@ -188,12 +114,6 @@ namespace PorygonSharp.UserData
|
|||
[DllImport("PorygonLang", EntryPoint = "RegisterUserDataType", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void RegisterUserDataType(uint hashId);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "RegisterUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void RegisterUserDataField(uint hashId, uint fieldId, IntPtr field);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateUserDataField", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateUserDataField(IntPtr type, IntPtr getter, IntPtr setter);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "GetUserDataFieldCount", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern int GetUserDataFieldCount(uint hashId);
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue