public void BindSignature_General()
        {
            var typeArgs1 = new[]
            {
                typeof(Random),
                typeof(string),
                typeof(Dictionary<string, DateTime>)
            };

            var typeArgs2 = new[]
            {
                typeof(Random),
                typeof(string),
                typeof(Dictionary<string, TimeSpan>)
            };

            var args1 = new object[]
            {
                int.MinValue,
                Math.E,
                "blah",
                new OutArg<DateTime>(DateTime.MinValue),
                new RefArg<TimeSpan>(TimeSpan.MinValue),
                DayOfWeek.Sunday
            };

            var args2 = new object[]
            {
                int.MaxValue,
                Math.PI,
                "meh",
                new OutArg<DateTime>(DateTime.MaxValue),
                new RefArg<TimeSpan>(TimeSpan.MaxValue),
                DayOfWeek.Saturday
            };

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(new HostVariable<string>(null), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable<string>(null), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable<string>(null), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(new HostVariable<string>("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable<string>("baz"), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("qux"), "foo", typeArgs1, args1);
                AssertEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "bar", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs2, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args2);
                AssertEqual(sig1, sig2);
            }
        }
 private static void AssertNotEqual(BindSignature sig1, BindSignature sig2)
 {
     Assert.AreNotEqual(sig1, sig2);
     Assert.AreNotEqual(sig1.GetHashCode(), sig2.GetHashCode());
 }
        private MethodBindResult BindMethod(string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
            // will result in bugs that are difficult to diagnose. Create a copy if necessary.

            var signature = new BindSignature(target, name, typeArgs, bindArgs);
            MethodBindResult result;

            object rawResult;
            if (engine.TryGetCachedBindResult(signature, out rawResult))
            {
                result = MethodBindResult.Create(name, rawResult, target, args);
            }
            else
            {
                result = BindMethodInternal(name, typeArgs, args, bindArgs);
                if (!result.IsPreferredMethod(name))
                {
                    if (result is MethodBindSuccess)
                    {
                        result = new MethodBindFailure(() => new MissingMemberException(MiscHelpers.FormatInvariant("Object has no method named '{0}' that matches the specified arguments", name)));
                    }

                    foreach (var altName in GetAltMethodNames(name))
                    {
                        var altResult = BindMethodInternal(altName, typeArgs, args, bindArgs);
                        if (altResult.IsUnblockedMethod())
                        {
                            result = altResult;
                            break;
                        }
                    }
                }

                engine.CacheBindResult(signature, result.RawResult);
            }

            return result;
        }
        public void BindSignature_General()
        {
            var typeArgs1 = new[]
            {
                typeof(Random),
                typeof(string),
                typeof(Dictionary <string, DateTime>)
            };

            var typeArgs2 = new[]
            {
                typeof(Random),
                typeof(string),
                typeof(Dictionary <string, TimeSpan>)
            };

            var args1 = new object[]
            {
                int.MinValue,
                Math.E,
                "blah",
                new OutArg <DateTime>(DateTime.MinValue),
                new RefArg <TimeSpan>(TimeSpan.MinValue),
                DayOfWeek.Sunday
            };

            var args2 = new object[]
            {
                int.MaxValue,
                Math.PI,
                "meh",
                new OutArg <DateTime>(DateTime.MaxValue),
                new RefArg <TimeSpan>(TimeSpan.MaxValue),
                DayOfWeek.Saturday
            };

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(new HostVariable <string>(null), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable <string>(null), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable <string>(null), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(new HostVariable <string>("baz"), "foo", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(new HostVariable <string>("baz"), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostObject.Wrap("qux"), "foo", typeArgs1, args1);
                AssertEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "bar", typeArgs1, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs2, args1);
                AssertNotEqual(sig1, sig2);
            }

            {
                var sig1 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args1);
                var sig2 = new BindSignature(HostType.Wrap(typeof(string)), "foo", typeArgs1, args2);
                AssertEqual(sig1, sig2);
            }
        }
 private static void AssertNotEqual(BindSignature sig1, BindSignature sig2)
 {
     Assert.AreNotEqual(sig1, sig2);
     Assert.AreNotEqual(sig1.GetHashCode(), sig2.GetHashCode());
 }
        private static MethodBindResult BindMethodInternal(Type bindContext, BindingFlags bindFlags, HostTarget target, string name, Type[] typeArgs, object[] args, object[] bindArgs)
        {
            // WARNING: BindSignature holds on to the specified typeArgs; subsequent modification
            // will result in bugs that are difficult to diagnose. Create a copy if necessary.

            var signature = new BindSignature(bindContext, bindFlags, target, name, typeArgs, bindArgs);
            MethodBindResult result;

            object rawResult;
            if (coreBindCache.TryGetValue(signature, out rawResult))
            {
                result = MethodBindResult.Create(name, rawResult, target, args);
            }
            else
            {
                result = BindMethodCore(bindContext, bindFlags, target, name, typeArgs, args, bindArgs);
                coreBindCache.TryAdd(signature, result.RawResult);
            }

            return result;
        }