12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- using System;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using Jint.Native;
- namespace Jint.Runtime.Descriptors.Specialized
- {
- public sealed class IndexDescriptor : PropertyDescriptor
- {
- private readonly Engine _engine;
- private readonly object _key;
- private readonly object _item;
- private readonly PropertyInfo _indexer;
- public IndexDescriptor(Engine engine, string key, object item)
- {
- _engine = engine;
- _item = item;
- // get all instance indexers with exactly 1 argument
- var indexers = item
- .GetType()
- .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
- .Where(x => x.GetIndexParameters().Length == 1);
-
- // try to find first indexer having either public getter or setter with matching argument type
- foreach (var indexer in indexers)
- {
- if (indexer.GetGetMethod() != null || indexer.GetSetMethod() != null)
- {
- var paramType = indexer.GetIndexParameters()[0].ParameterType;
- try
- {
- _key = _engine.Options.GetTypeConverter().Convert(key, paramType, CultureInfo.InvariantCulture);
- _indexer = indexer;
- break;
- }
- catch { }
- }
- }
- // throw if no indexer found
- if(_indexer == null)
- throw new InvalidOperationException("No matching indexer found.");
- Writable = true;
- }
- public override JsValue? Value
- {
- get
- {
- var getter = _indexer.GetGetMethod();
- if(getter == null)
- throw new InvalidOperationException("Indexer has no public getter.");
- object[] parameters = { _key };
- return JsValue.FromObject(_engine, getter.Invoke(_item, parameters));
- }
- set
- {
- var setter = _indexer.GetSetMethod();
- if (setter == null)
- throw new InvalidOperationException("Indexer has no public setter.");
- object[] parameters = { _key, value.HasValue ? value.Value.ToObject() : null };
- setter.Invoke(_item, parameters);
- }
- }
- }
- }
|