DynamicObjectAccessor.cs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using System.Dynamic;
  2. using System.Reflection;
  3. using Jint.Native;
  4. namespace Jint.Runtime.Interop.Reflection
  5. {
  6. internal sealed class DynamicObjectAccessor : ReflectionAccessor
  7. {
  8. private readonly string _memberName;
  9. private JintSetMemberBinder? _setter;
  10. private JintGetMemberBinder? _getter;
  11. public DynamicObjectAccessor(
  12. Type memberType,
  13. string memberName,
  14. PropertyInfo? indexer = null) : base(memberType, memberName, indexer)
  15. {
  16. _memberName = memberName;
  17. }
  18. public override bool Writable => true;
  19. protected override object? DoGetValue(object target)
  20. {
  21. var dynamicObject = (DynamicObject) target;
  22. var getter = _getter ??= new JintGetMemberBinder(_memberName, ignoreCase: true);
  23. dynamicObject.TryGetMember(getter, out var result);
  24. return result;
  25. }
  26. protected override void DoSetValue(object target, object? value)
  27. {
  28. var dynamicObject = (DynamicObject) target;
  29. var setter = _setter ??= new JintSetMemberBinder(_memberName, ignoreCase: true);
  30. dynamicObject.TrySetMember(setter, value);
  31. }
  32. protected override object? ConvertValueToSet(Engine engine, object value)
  33. {
  34. // we expect value to be generally CLR type, convert when possible
  35. return value switch
  36. {
  37. JsBoolean jsBoolean => jsBoolean._value ? JsBoolean.BoxedTrue : JsBoolean.BoxedFalse,
  38. JsString jsString => jsString.ToString(),
  39. JsNumber jsNumber => jsNumber._value,
  40. JsNull => null,
  41. JsUndefined => null,
  42. _ => value
  43. };
  44. }
  45. private sealed class JintGetMemberBinder : GetMemberBinder
  46. {
  47. public JintGetMemberBinder(string name, bool ignoreCase) : base(name, ignoreCase)
  48. {
  49. }
  50. public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion)
  51. {
  52. throw new NotImplementedException(nameof(FallbackGetMember) + " not implemented");
  53. }
  54. }
  55. private sealed class JintSetMemberBinder : SetMemberBinder
  56. {
  57. public JintSetMemberBinder(string name, bool ignoreCase) : base(name, ignoreCase)
  58. {
  59. }
  60. public override DynamicMetaObject FallbackSetMember(
  61. DynamicMetaObject target,
  62. DynamicMetaObject value,
  63. DynamicMetaObject? errorSuggestion)
  64. {
  65. throw new NotImplementedException(nameof(FallbackSetMember) + " not implemented");
  66. }
  67. }
  68. }
  69. }