Support properties and readonly fields
This commit is contained in:
		| @@ -17,31 +17,82 @@ namespace PorygonSharp.UserData | ||||
|         { | ||||
|             var hash = name.ScriptHash(); | ||||
|             RegisterUserDataType(hash); | ||||
|             if (UserDataLookup.ContainsKey(type)) | ||||
|                 return; | ||||
|             UserDataLookup.Add(type, hash); | ||||
|  | ||||
|             var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); | ||||
|             const BindingFlags bindingFlags = BindingFlags.Public           | BindingFlags.Instance | | ||||
|                                               BindingFlags.FlattenHierarchy | BindingFlags.Static; | ||||
|             var fields = type.GetFields(bindingFlags); | ||||
|             foreach (var field in fields) | ||||
|             { | ||||
|                 var getter = new GetterDelegate(ptr => | ||||
|                 { | ||||
|                     var obj = GCHandle.FromIntPtr(ptr).Target; | ||||
|                     var value = field.GetValue(obj); | ||||
|                     return new EvalValue(value).GetPointer(); | ||||
|                 }); | ||||
|                 RegisterField(field, hash); | ||||
|             } | ||||
|  | ||||
|             var properties = type.GetProperties(bindingFlags); | ||||
|             foreach (var property in properties) | ||||
|             { | ||||
|                 RegisterProperty(property, hash); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private static void RegisterField(FieldInfo field, uint typeHash) | ||||
|         { | ||||
|             var getter = new GetterDelegate(ptr => | ||||
|             { | ||||
|                 var obj   = GCHandle.FromIntPtr(ptr).Target; | ||||
|                 var value = field.GetValue(obj); | ||||
|                 return new EvalValue(value).GetPointer(); | ||||
|             }); | ||||
|  | ||||
|             var setterPtr = IntPtr.Zero; | ||||
|             if (!field.IsInitOnly) | ||||
|             { | ||||
|                 var setter = new SetterDelegate((ptr, val) => | ||||
|                 { | ||||
|                     var obj = GCHandle.FromIntPtr(ptr).Target; | ||||
|                     var obj       = GCHandle.FromIntPtr(ptr).Target; | ||||
|                     var evalValue = Convert.ChangeType(new EvalValue(val).GetObjectValue(), field.FieldType); | ||||
|                     field.SetValue(obj, evalValue); | ||||
|                 }); | ||||
|                 var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType); | ||||
|                 var userDataField = CreateUserDataField(scriptType, Marshal.GetFunctionPointerForDelegate(getter), | ||||
|                     Marshal.GetFunctionPointerForDelegate(setter)); | ||||
|  | ||||
|  | ||||
|                 var fieldName = field.Name.ScriptHash(); | ||||
|                 RegisterUserDataField(hash, fieldName, userDataField); | ||||
|                 setterPtr = Marshal.GetFunctionPointerForDelegate(setter); | ||||
|             } | ||||
|             var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType); | ||||
|             var userDataField = CreateUserDataField(scriptType, Marshal.GetFunctionPointerForDelegate(getter), | ||||
|                 setterPtr); | ||||
|  | ||||
|             var fieldName = field.Name.ScriptHash(); | ||||
|             RegisterUserDataField(typeHash, fieldName, userDataField); | ||||
|         } | ||||
|  | ||||
|         private static void RegisterProperty(PropertyInfo property, uint typeHash) | ||||
|         { | ||||
|             var getterPtr = IntPtr.Zero; | ||||
|             if (property.GetGetMethod(false) != null) | ||||
|             { | ||||
|                 var getter = new GetterDelegate(ptr => | ||||
|                 { | ||||
|                     var obj   = GCHandle.FromIntPtr(ptr).Target; | ||||
|                     var value = property.GetValue(obj); | ||||
|                     return new EvalValue(value).GetPointer(); | ||||
|                 }); | ||||
|                 getterPtr = Marshal.GetFunctionPointerForDelegate(getter); | ||||
|             } | ||||
|             var setterPtr = IntPtr.Zero; | ||||
|             if (property.GetSetMethod(false) != null) | ||||
|             { | ||||
|                 var setter = new SetterDelegate((ptr, val) => | ||||
|                 { | ||||
|                     var obj       = GCHandle.FromIntPtr(ptr).Target; | ||||
|                     var evalValue = Convert.ChangeType(new EvalValue(val).GetObjectValue(), property.PropertyType); | ||||
|                     property.SetValue(obj, evalValue); | ||||
|                 }); | ||||
|                 setterPtr = Marshal.GetFunctionPointerForDelegate(setter); | ||||
|             } | ||||
|             var scriptType = ScriptType.ScriptType.GetScriptType(property.PropertyType); | ||||
|             var userDataField = CreateUserDataField(scriptType, getterPtr, setterPtr); | ||||
|  | ||||
|             var fieldName = property.Name.ScriptHash(); | ||||
|             RegisterUserDataField(typeHash, fieldName, userDataField); | ||||
|         } | ||||
|  | ||||
|         public static uint GetTypeId(Type t) | ||||
| @@ -49,6 +100,12 @@ namespace PorygonSharp.UserData | ||||
|             return UserDataLookup[t]; | ||||
|         } | ||||
|  | ||||
|         public static int GetUserDataFieldCount(Type t) | ||||
|         { | ||||
|             var hash = GetTypeId(t); | ||||
|             return GetUserDataFieldCount(hash); | ||||
|         } | ||||
|  | ||||
|         [DllImport("libPorygonLang", EntryPoint = "RegisterUserDataType", CallingConvention = CallingConvention.Cdecl)] | ||||
|         private static extern void RegisterUserDataType(uint hashId); | ||||
|  | ||||
|   | ||||
| @@ -109,59 +109,6 @@ namespace PorygonSharpTests | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private class UserDataTestObject | ||||
|         { | ||||
|             public int Foo = 200; | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Test9() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     result = v['Foo'] | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 script.CallFunction("test", new UserDataTestObject()); | ||||
|                 var variable = script.GetVariable("result"); | ||||
|                 Assert.AreEqual(200, variable.EvaluateInteger()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void Test10() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     v['Foo'] = 20000 | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 var parameter = new UserDataTestObject(); | ||||
|                 script.CallFunction("test", parameter); | ||||
|                 Assert.AreEqual(20000, parameter.Foo); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void TestHash() | ||||
|         { | ||||
|   | ||||
							
								
								
									
										150
									
								
								PorygonSharpTests/UserDataTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								PorygonSharpTests/UserDataTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| using NUnit.Framework; | ||||
| using PorygonSharp; | ||||
| using PorygonSharp.UserData; | ||||
|  | ||||
| namespace PorygonSharpTests | ||||
| { | ||||
|     [TestFixture] | ||||
|     public class UserDataTests | ||||
|     { | ||||
|         private class UserDataTestObject | ||||
|         { | ||||
|             public int Foo = 200; | ||||
|             public int Bar { get; set; } | ||||
|             public int GetOnly { get; } = 865; | ||||
|             public readonly int ReadOnly = 684; | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void CanGetFromUserDataField() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     result = v['Foo'] | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 script.CallFunction("test", new UserDataTestObject()); | ||||
|                 var variable = script.GetVariable("result"); | ||||
|                 Assert.AreEqual(200, variable.EvaluateInteger()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void CanSetToUserDataField() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     v['Foo'] = 20000 | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 var parameter = new UserDataTestObject(); | ||||
|                 script.CallFunction("test", parameter); | ||||
|                 Assert.AreEqual(20000, parameter.Foo); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void CanGetFromPropertyWithoutSetter() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     result = v['GetOnly'] | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 var parameter = new UserDataTestObject(); | ||||
|                 script.CallFunction("test", parameter); | ||||
|                 Assert.AreEqual(865, script.GetVariable("result").EvaluateInteger()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void CantSetToPropertyWithoutSetter() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     v['GetOnly'] = 10000 | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics().ToArray(); | ||||
|                 Assert.IsNotEmpty(diags); | ||||
|                 Assert.AreEqual(1, diags.Length); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         [Test] | ||||
|         public void CanGetFromReadonlyField() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     result = v['ReadOnly'] | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics(); | ||||
|                 foreach (var diag in diags) | ||||
|                 { | ||||
|                     throw new Exception(diag.GetCode().ToString()); | ||||
|                 } | ||||
|  | ||||
|                 script.Evaluate(); | ||||
|  | ||||
|                 var parameter = new UserDataTestObject(); | ||||
|                 script.CallFunction("test", parameter); | ||||
|                 Assert.AreEqual(684, script.GetVariable("result").EvaluateInteger()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         [Test] | ||||
|         public void CantSetToReadonlyField() | ||||
|         { | ||||
|             UserDataHandler.RegisterType("testObject", typeof(UserDataTestObject)); | ||||
|             using (var script = Script.CreateScript(@" | ||||
| function test(testObject v) | ||||
|     v['ReadOnly'] = 10000 | ||||
| end | ||||
| ")) | ||||
|             { | ||||
|                 var diags = script.Diagnostics.GetDiagnostics().ToArray(); | ||||
|                 Assert.IsNotEmpty(diags); | ||||
|                 Assert.AreEqual(1, diags.Length); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user