Browse Source

Added support for explicit interface implentations

Stephan Müller 11 years ago
parent
commit
8c93ff5979

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

@@ -59,6 +59,8 @@
     <Compile Include="Runtime\Domain\ClassWithField.cs" />
     <Compile Include="Runtime\Domain\ClassWithStaticFields.cs" />
     <Compile Include="Runtime\Domain\Colors.cs" />
+    <Compile Include="Runtime\Domain\Company.cs" />
+    <Compile Include="Runtime\Domain\ICompany.cs" />
     <Compile Include="Runtime\Domain\IPerson.cs" />
     <Compile Include="Runtime\Domain\Person.cs" />
     <Compile Include="Runtime\Domain\Shape.cs" />

+ 36 - 0
Jint.Tests/Runtime/Domain/Company.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jint.Tests.Runtime.Domain
+{
+    public class Company : ICompany, IComparable<ICompany>
+    {
+        private string _name;
+        private readonly Dictionary<string, string> _dictionary = new Dictionary<string, string>();
+
+        public Company(string name)
+        {
+            _name = name;
+        }
+
+        string ICompany.Name
+        {
+            get { return _name; }
+            set { _name = value; }
+        }
+
+        string ICompany.this[string key]
+        {
+            get { return _dictionary[key]; }
+            set { _dictionary[key] = value; }
+        }
+
+        int IComparable<ICompany>.CompareTo(ICompany other)
+        {
+            return string.Compare(_name, other.Name, StringComparison.CurrentCulture);
+        }
+    }
+}

+ 8 - 0
Jint.Tests/Runtime/Domain/ICompany.cs

@@ -0,0 +1,8 @@
+namespace Jint.Tests.Runtime.Domain
+{
+    public interface ICompany
+    {
+        string Name { get; set; }
+        string this[string key] { get; set; }
+    }
+}

File diff suppressed because it is too large
+ 679 - 679
Jint.Tests/Runtime/InteropTests.cs


+ 12 - 4
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -1,4 +1,5 @@
-using System.Globalization;
+using System;
+using System.Globalization;
 using System.Reflection;
 using Jint.Native;
 
@@ -12,19 +13,26 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly MethodInfo _getter;
         private readonly MethodInfo _setter;
 
-        public IndexDescriptor(Engine engine, string key, object item)
+        public IndexDescriptor(Engine engine, Type targetType, string key, object item)
         {
             _engine = engine;
             _item = item;
 
-            _getter = item.GetType().GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
-            _setter = item.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
+            _getter = targetType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
+            _setter = targetType.GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
 
             _key = _engine.Options.GetTypeConverter().Convert(key, _getter.GetParameters()[0].ParameterType, CultureInfo.InvariantCulture);
 
             Writable = true;
         }
 
+
+        public IndexDescriptor(Engine engine, string key, object item)
+            : this(engine, item.GetType(), key, item)
+        {
+            
+        }
+
         public override JsValue? Value
         {
             get

+ 132 - 94
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -1,93 +1,93 @@
-using System;
-using System.Linq;
-using System.Reflection;
-using Jint.Native;
-using Jint.Native.Object;
-using Jint.Runtime.Descriptors;
+using System;
+using System.Linq;
+using System.Reflection;
+using Jint.Native;
+using Jint.Native.Object;
+using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors.Specialized;
-using System.Collections;
-
-namespace Jint.Runtime.Interop
-{
-    /// <summary>
-    /// Wrapps a CLR instance
-    /// </summary>
-    public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper
-    {
-        public Object Target { get; set; }
-
-        public ObjectWrapper(Engine engine, Object obj): base(engine)
-        {
-            Target = obj;
-        }
-
-        public override void Put(string propertyName, JsValue value, bool throwOnError)
-        {
-            if (!CanPut(propertyName))
-            {
-                if (throwOnError)
-                {
-                    throw new JavaScriptException(Engine.TypeError);
-                }
-
-                return;
-            }
-
-            var ownDesc = GetOwnProperty(propertyName);
-
-            if (ownDesc == null)
-            {
-                if (throwOnError)
-                {
-                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
-                }
-                else
-                {
-                    return;
-                }
-            }
-
-            ownDesc.Value = value;
-        }
-
-        public override PropertyDescriptor GetOwnProperty(string propertyName)
-        {
-            PropertyDescriptor x;
-            if (Properties.TryGetValue(propertyName, out x))
-            {
-                return x;
-            }
-
-            var type = Target.GetType();
-
-            // look for a property
-            var property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
-
-            if (property != null)
-            {
-                var descriptor = new PropertyInfoDescriptor(Engine, property, Target);
-                Properties.Add(propertyName, descriptor);
-                return descriptor;
-            }
-
-            // look for a field
-            var field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public);
-
-            if (field != null)
-            {
-                var descriptor = new FieldInfoDescriptor(Engine, field, Target);
-                Properties.Add(propertyName, descriptor);
-                return descriptor;
-            }
-
-            // if no properties were found then look for a method 
-            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
-                .Where(m => m.Name == propertyName)
-                .ToArray();
-
-            if (methods.Any())
-            {
-                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, methods), false, true, false);
+using System.Collections;
+
+namespace Jint.Runtime.Interop
+{
+    /// <summary>
+    /// Wrapps a CLR instance
+    /// </summary>
+    public sealed class ObjectWrapper : ObjectInstance, IObjectWrapper
+    {
+        public Object Target { get; set; }
+
+        public ObjectWrapper(Engine engine, Object obj): base(engine)
+        {
+            Target = obj;
+        }
+
+        public override void Put(string propertyName, JsValue value, bool throwOnError)
+        {
+            if (!CanPut(propertyName))
+            {
+                if (throwOnError)
+                {
+                    throw new JavaScriptException(Engine.TypeError);
+                }
+
+                return;
+            }
+
+            var ownDesc = GetOwnProperty(propertyName);
+
+            if (ownDesc == null)
+            {
+                if (throwOnError)
+                {
+                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
+                }
+                else
+                {
+                    return;
+                }
+            }
+
+            ownDesc.Value = value;
+        }
+
+        public override PropertyDescriptor GetOwnProperty(string propertyName)
+        {
+            PropertyDescriptor x;
+            if (Properties.TryGetValue(propertyName, out x))
+            {
+                return x;
+            }
+
+            var type = Target.GetType();
+
+            // look for a property
+            var property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
+
+            if (property != null)
+            {
+                var descriptor = new PropertyInfoDescriptor(Engine, property, Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // look for a field
+            var field = type.GetField(propertyName, BindingFlags.Instance | BindingFlags.Public);
+
+            if (field != null)
+            {
+                var descriptor = new FieldInfoDescriptor(Engine, field, Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // if no properties were found then look for a method 
+            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public)
+                .Where(m => m.Name == propertyName)
+                .ToArray();
+
+            if (methods.Any())
+            {
+                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, methods), false, true, false);
             }
 
             // if no methods are found check if target implemented indexing
@@ -95,8 +95,46 @@ namespace Jint.Runtime.Interop
             {
                 return new IndexDescriptor(Engine, propertyName, Target);
             }
-
-            return PropertyDescriptor.Undefined;
-        }
-    }
-}
+
+            var interfaces = type.GetInterfaces();
+
+            // try to find a single explicit property implementation
+            var explicitProperties = (from iface in interfaces
+                from iprop in iface.GetProperties()
+                where propertyName.Equals(iprop.Name)
+                select iprop).ToList();
+
+            if (explicitProperties.Count == 1)
+            {
+                var descriptor = new PropertyInfoDescriptor(Engine, explicitProperties[0], Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // try to find explicit method implementations
+            var explicitMethods = (from iface in interfaces
+                from imethod in iface.GetMethods()
+                where propertyName.Equals(imethod.Name)
+                select imethod).ToList();
+
+            if (explicitMethods.Count > 0)
+            {
+                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, explicitMethods.ToArray()), false, true, false);
+            }
+
+            // try to find explicit indexer implementations
+            var explicitIndexers =
+                (from iface in interfaces
+                    from iprop in iface.GetProperties()
+                    where iprop.GetIndexParameters().Length != 0
+                    select iprop).ToList();
+
+            if (explicitIndexers.Count == 1)
+            {
+                return new IndexDescriptor(Engine, explicitIndexers[0].DeclaringType, propertyName, Target);
+            }
+
+            return PropertyDescriptor.Undefined;
+        }
+    }
+}

Some files were not shown because too many files changed in this diff