Răsfoiți Sursa

Merge pull request #70 from chaquotay/feature/explicitinterfaces

Added support for explicit interface implentations
Sébastien Ros 11 ani în urmă
părinte
comite
971600bdca

+ 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; }
+    }
+}

+ 59 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -939,7 +939,65 @@ namespace Jint.Tests.Runtime
             ");
 
             Assert.Equal(Colors.Blue | Colors.Green, s.Color);
-        }
+        }
+
+        [Fact]
+        public void ShouldUseExplicitPropertyGetter()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                assert(c.Name === 'ACME');
+            ");
+        }
+
+        [Fact]
+        public void ShouldUseExplicitIndexerPropertyGetter()
+        {
+            var company = new Company("ACME");
+            ((ICompany)company)["Foo"] = "Bar";
+            _engine.SetValue("c", company);
+
+            RunTest(@"
+                assert(c.Foo === 'Bar');
+            ");
+        }
+
+
+        [Fact]
+        public void ShouldUseExplicitPropertySetter()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                c.Name = 'Foo';
+                assert(c.Name === 'Foo');
+            ");
+        }
+
+        [Fact]
+        public void ShouldUseExplicitIndexerPropertySetter()
+        {
+            var company = new Company("ACME");
+            ((ICompany)company)["Foo"] = "Bar";
+            _engine.SetValue("c", company);
+
+            RunTest(@"
+                c.Foo = 'Baz';
+                assert(c.Foo === 'Baz');
+            ");
+        }
+
+
+        [Fact]
+        public void ShouldUseExplicitMethod()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                assert(0 === c.CompareTo(c));
+            ");
+        }
 
     }
 }

+ 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.ClrTypeConverter.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

+ 38 - 0
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -95,6 +95,44 @@ namespace Jint.Runtime.Interop
             {
                 return new IndexDescriptor(Engine, propertyName, Target);
             }
+
+            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;
         }