ソースを参照

Implementing object converters

#18
Sebastien Ros 11 年 前
コミット
978bb0e211

+ 1 - 0
Jint.Tests/Jint.Tests.csproj

@@ -54,6 +54,7 @@
   <ItemGroup>
     <Compile Include="Parser\JavascriptParserTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Runtime\Converters\NegateBoolConverter.cs" />
     <Compile Include="Runtime\Domain\A.cs" />
     <Compile Include="Runtime\Domain\ClassWithField.cs" />
     <Compile Include="Runtime\Domain\IPerson.cs" />

+ 20 - 0
Jint.Tests/Runtime/Converters/NegateBoolConverter.cs

@@ -0,0 +1,20 @@
+using Jint.Native;
+using Jint.Runtime.Interop;
+
+namespace Jint.Tests.Runtime.Converters
+{
+    public class NegateBoolConverter : IObjectConverter
+    {
+        public bool TryConvert(object value, out JsValue result)
+        {
+            if (value is bool)
+            {
+                result = !(bool) value;
+                return true;
+            }
+
+            result = JsValue.Null;
+            return false;
+        }
+    }
+}

+ 17 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using Jint.Native;
 using Jint.Native.Object;
+using Jint.Tests.Runtime.Converters;
 using Jint.Tests.Runtime.Domain;
 using Shapes;
 using Xunit;
@@ -546,6 +547,22 @@ namespace Jint.Tests.Runtime
             Assert.Equal("Mickey Mouse", o.Field);
         }
 
+        [Fact]
+        public void CanSetCustomConverters()
+        {
+
+            var engine1 = new Engine();
+            engine1.SetValue("p", new { Test = true });
+            engine1.Execute("var result = p.Test;");
+            Assert.True((bool)engine1.GetValue("result").ToObject());
+
+            var engine2 = new Engine(o => o.AddObjectConverter(new NegateBoolConverter()));
+            engine2.SetValue("p", new { Test = true });
+            engine2.Execute("var result = p.Test;");
+            Assert.False((bool)engine2.GetValue("result").ToObject());
+
+        }
+
 
     }
 }

+ 1 - 0
Jint/Jint.csproj

@@ -173,6 +173,7 @@
     <Compile Include="Runtime\ExpressionIntepreter.cs" />
     <Compile Include="Runtime\Interop\DefaultTypeConverter.cs" />
     <Compile Include="Runtime\Interop\IObjectWrapper.cs" />
+    <Compile Include="Runtime\Interop\IObjectConverter.cs" />
     <Compile Include="Runtime\Interop\ITypeConverter.cs" />
     <Compile Include="Runtime\Interop\MethodInfoFunctionInstance.cs" />
     <Compile Include="Runtime\Interop\ClrFunctionInstance.cs" />

+ 9 - 0
Jint/Native/JsValue.cs

@@ -280,6 +280,15 @@ namespace Jint.Native
                 return Null;
             }
 
+            foreach(var converter in engine.Options.GetObjectConverters())
+            {
+                JsValue result;
+                if (converter.TryConvert(value, out result))
+                {
+                    return result;
+                }
+            }
+
             var typeCode = System.Type.GetTypeCode(value.GetType());
             switch (typeCode)
             {

+ 16 - 0
Jint/Options.cs

@@ -2,6 +2,7 @@
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
+using Jint.Native;
 using Jint.Runtime.Interop;
 
 namespace Jint
@@ -13,6 +14,7 @@ namespace Jint
         private bool _allowDebuggerStatement;
         private bool _allowClr;
         private ITypeConverter _typeConverter = new DefaultTypeConverter();
+        private readonly List<IObjectConverter> _objectConverters = new List<IObjectConverter>();
         private int _maxStatements;
         private CultureInfo _culture = CultureInfo.CurrentCulture;
         private List<Assembly> _lookupAssemblies = new List<Assembly>(); 
@@ -58,6 +60,15 @@ namespace Jint
             return this;
         }
 
+        /// <summary>
+         /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
+        /// </summary>
+        public Options AddObjectConverter(IObjectConverter objectConverter)
+        {
+            _objectConverters.Add(objectConverter);
+            return this;
+        }
+
         /// <summary>
         /// Allows scripts to call CLR types directly like <example>System.IO.File</example>
         /// </summary>
@@ -111,6 +122,11 @@ namespace Jint
             return _typeConverter;
         }
 
+        internal IEnumerable<IObjectConverter> GetObjectConverters()
+        {
+            return _objectConverters;
+        }
+
         internal int GetMaxStatements()
         {
             return _maxStatements;

+ 12 - 0
Jint/Runtime/Interop/IObjectConverter.cs

@@ -0,0 +1,12 @@
+using Jint.Native;
+
+namespace Jint.Runtime.Interop
+{
+    /// <summary>
+    /// When implemented, converts a CLR value to a <see cref="JsValue"/> instance
+    /// </summary>
+    public interface IObjectConverter
+    {
+        bool TryConvert(object value, out JsValue result);
+    }
+}