ReflectionDescriptor.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System.Reflection;
  2. using Jint.Native;
  3. using Jint.Runtime.Interop;
  4. using Jint.Runtime.Interop.Reflection;
  5. namespace Jint.Runtime.Descriptors.Specialized;
  6. internal sealed class ReflectionDescriptor : PropertyDescriptor
  7. {
  8. private readonly Engine _engine;
  9. private readonly ReflectionAccessor _reflectionAccessor;
  10. private readonly object _target;
  11. private readonly string _propertyName;
  12. private JsValue? _get;
  13. private JsValue? _set;
  14. public ReflectionDescriptor(
  15. Engine engine,
  16. ReflectionAccessor reflectionAccessor,
  17. object target,
  18. string propertyName,
  19. bool enumerable)
  20. : base((enumerable ? PropertyFlag.Enumerable : PropertyFlag.None) | PropertyFlag.CustomJsValue)
  21. {
  22. _flags |= PropertyFlag.NonData;
  23. _engine = engine;
  24. _reflectionAccessor = reflectionAccessor;
  25. _target = target;
  26. _propertyName = propertyName;
  27. }
  28. public override JsValue? Get
  29. {
  30. get
  31. {
  32. if (_reflectionAccessor.Readable)
  33. {
  34. return _get ??= new GetterFunction(_engine, DoGet);
  35. }
  36. return null;
  37. }
  38. }
  39. public override JsValue? Set
  40. {
  41. get
  42. {
  43. if (_reflectionAccessor.Writable && _engine.Options.Interop.AllowWrite)
  44. {
  45. return _set ??= new SetterFunction(_engine, DoSet);
  46. }
  47. return null;
  48. }
  49. }
  50. protected internal override JsValue? CustomValue
  51. {
  52. get => DoGet(thisObj: null);
  53. set => DoSet(thisObj: null, value);
  54. }
  55. private JsValue DoGet(JsValue? thisObj)
  56. {
  57. var value = _reflectionAccessor.GetValue(_engine, _target, _propertyName);
  58. var type = _reflectionAccessor.MemberType ?? value?.GetType();
  59. return JsValue.FromObjectWithType(_engine, value, type);
  60. }
  61. private void DoSet(JsValue? thisObj, JsValue? v)
  62. {
  63. try
  64. {
  65. _reflectionAccessor.SetValue(_engine, _target, _propertyName, v!);
  66. }
  67. catch (TargetInvocationException exception)
  68. {
  69. ExceptionHelper.ThrowMeaningfulException(_engine, exception);
  70. }
  71. }
  72. }