2017-09-08 5 views
2

で辞書を<>列挙する方法を私は私がJINTで実行しているJavaScript関数に渡したいという.NETジェネリック辞書<>を持っています。はJINT

Jintは、辞書のように扱えるJavaScriptオブジェクトのように.NET辞書を扱いません。オブジェクトの.NETプロパティとメソッドにはアクセスできますが、拡張メソッドにはアクセスできません。私は辞書のキーの数を取得することができますしながら、

だから私はそれを列挙したり、その上に()たToArrayを呼び出すことはできません。

私は辞書から値を読み取るために辞書[キー]を使用することができますが、この例では、私は事前にキーを知りません。

キーを列挙するか、.NET Generic Dictionaryのすべてのエントリを取得するにはどうすればよいですか?

は私が辞書に何かをするか、私はそれにそれを渡す前に、それを変換するか、JavaScriptでそれを行う方法を考え出すに開いています。私はキーの配列を別々に渡す必要がないことを望むだろう。これは別のデータ構造の中にあり、辞書ごとにそれを行うと複雑になりますが、別の解決策が見つからない場合は、私が検討しているオプションの1つです。

ダイナミクスを使用しないようにしてください。私は過去に大量に使用されたときにメモリが漏れていることに問題がありました。

+0

私は[タグ:JINT]使ったことがない前に、しかし、あなたの質問は、JavaScriptでのオブジェクトのメンバーを列挙する方法であるように見えます。 javascript *のオブジェクトは*ディクショナリであり、通常はそのようにシリアライズされます。 [This](https://stackoverflow.com/questions/684672/how-do-i-loop-through-or-enumerate-a-javascript-object)はおそらくあなたの質問に答えます – Rob

+0

あなたはjavascriptのようなオブジェクトプロパティを繰り返し処理できます[this](https://stackoverflow.com/questions/85992/how-do-i-enumerate-the-properties-of-a-javascript-object)しかし、あなたが望むものを正確に伝えるのは難しいですここでやる.net側では、 'Dictionary ' KeyCollectionを列挙し、すべてのキーのリストを取得することができます。 –

+0

はjintでは機能しません。それはオブジェクトがJavaScriptで宣言されていたので、私はそれを行う通常のjsの方法を使うことができました。NETオブジェクトはjs環境に渡され、通常のjsオブジェクトのように扱うことはできません。私はすでに具体的に(var i in mydict)と(var i in mydict.Keys)どちらもうまくいきませんでした。 – Zack

答えて

2

// 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 
} 

あなたがいない場合、あなただけのmyDictionary.KeysまたはmyDictionary.Valuesを繰り返すことができ、同じように両方に興味がある。

注:dict[key]を使用できます。少なくとも私にとって複雑なものがあったのはstructです。これはうまくいきませんでした。どうやらJintはジェネリックインデクサーをうまく処理できず、スローします。System.InvalidOperationException:一致するインデクサーが見つかりません。

0

あなたはそれのターゲットオブジェクトのToArray方法を解決する独自のObjectWrapperを作成することができます。ここでは、エラー処理のようなものを改善する必要があります、それを私の迅速な刺しだが、それはスタートだ:あなたの特定の状況に合うかもしれない

public class ObjectWrapperExt: ObjectInstance, IObjectWrapper 
{ 
    private ObjectWrapper _target; 

    public ObjectWrapperExt(Engine engine, Object obj) 
     : base(engine) 
    { 
     _target = new ObjectWrapper(engine, obj); 
    } 
    public object Target => _target.Target; 

    public override PropertyDescriptor GetOwnProperty(string propertyName) 
    { 

     if (propertyName == "ToArray") 
     { 
      if (this.Properties.TryGetValue(propertyName, out var prop)) return prop; 

      var descriptor = new PropertyDescriptor(new ToArrayFunctionInstance(Engine), false, true, false); 
      Properties.Add(propertyName, descriptor); 
      return descriptor; 
     } 

     return _target.GetOwnProperty(propertyName); 
    } 

    public override void Put(string propertyName, JsValue value, bool throwOnError) 
    { 
     _target.Put(propertyName, value, throwOnError); 
    } 

    public class ToArrayFunctionInstance : FunctionInstance 
    { 
     private static MethodInfo toArray = typeof(Enumerable).GetMethod("ToArray", BindingFlags.Static | BindingFlags.Public); 

     public ToArrayFunctionInstance(Engine engine) : base(engine, null,null, false) 
     { 
     } 

     public override JsValue Call(JsValue thisObject, JsValue[] arguments) 
     { 
      var target = (thisObject.AsObject() is IObjectWrapper w)? w.Target : throw new NotSupportedException(); 
      var targetType = target.GetType(); 

      var enumImpl = targetType.GetInterfaces() 
       .Where(_ => _.IsGenericType) 
       .Where(_ => _.GetGenericTypeDefinition() == typeof(IEnumerable<>)) 
       .FirstOrDefault(); 

      if(enumImpl != null) 
      { 
       var arg = enumImpl.GetGenericArguments(); 
       var value = toArray.MakeGenericMethod(arg).Invoke(null, new[] { target }); 
       return JsValue.FromObject(Engine, value); 
      } 
      throw new NotSupportedException(); 
     } 
    } 
} 
1

簡単な代替ではなく、JSONとして値を渡すことです。特にjintを使用してテストを書くときに、これが便利なケースがたくさんあります。これはシリアライザへの依存関係を追加しますが、おそらく遅くなりますが、非常に便利で確実に予測可能でデバッグ可能です。

私はちょうど同じ問題に遭遇したと辞書に列挙子を使用して、それを解決し
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})"); 
     } 
    } 
} 
+0

あなたは天才です! –

関連する問題