Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Enumerate a Dictionary<> in Jint

I have a .NET Generic Dictionary<> that I want to pass to a JavaScript function which I am running in Jint.

Jint doesn't treat the .NET Dictionary like a JavaScript object which can be treated like a Dictionary. You can access the .NET properties and methods on the object but not the Extension methods.

So while I can get a count of the Dictionary Keys I cannot enumerate it or call ToArray() on it.

I can used dict[key] to read values out of the Dictionary but in this instance I do not know the keys in advance.

How can I enumerate the keys or get all entries in the .NET Generic Dictionary?

I'm open to doing something to the dictionary or converting it before I pass it it in or figuring out how to do it in the JavaScript. I would prefer not to have to pass an array of the keys separately. This is inside another data structure and doing that for each dictionary would make it more complicated but it is one of the options that I'm considering if I can't find another solution.

I would prefer to stay away from using dynamics. I've had trouble with them leaking memory when used heavily in the past.

like image 247
Zack Avatar asked Mar 09 '23 03:03

Zack


2 Answers

I just ran into the same problem and solved it by using the enumerator on the dictionary:

// Javascript in Jint:
var enumerator = myDictionary.GetEnumerator();
while (enumerator.MoveNext()) {
    var key = enumerator.Current.Key;
    var value = enumerator.Current.Value;
    // do stuff with key and/or value
}

The same way you could just iterate myDictionary.Keys or myDictionary.Values if you are not interested in both.

Note: You mentioned you could use dict[key]. At least for me where I had a complex struct as key, this didn't work. Apparently Jint can't handle generic indexers well and throws: System.InvalidOperationException: No matching indexer found.

like image 130
djk Avatar answered Mar 19 '23 12:03

djk


An simple alternative that might fit your particular situation is to pass the value as JSON instead. There are many cases when this is useful, particularly when writing tests using jint. This adds a dependency on a serializer though, and is probably slower, but very convenient and certainly predictable and debuggable.

using Jint;
using Newtonsoft.Json;

namespace Extensions
{
    public static class EngineExtentions {
        public static void SetJsonValue(this Engine source, string name, object value)
        {
            source.SetValue(name, JsonConvert.SerializeObject(value));
            source.Execute($"{name} = JSON.parse({name})");
        }
    }
}
like image 28
Tewr Avatar answered Mar 19 '23 11:03

Tewr