public void Combinatorial_Test_All_1_Argument_Dispatch(
            [Values("A", "B", "C", "D")] string arg1)
        {
            A a1 = DispatchTestHelper.CreateInstance(arg1);

            DispatchTestHelper check = new DispatchTestHelper();

            Assert.AreEqual(arg1, check.FF1(a1));
        }
        public void Combinatorial_Test_All_2_Argument_Dispatch(
            [Values("A", "B", "C", "D")] string arg1,
            [Values("A", "B", "C", "D")] string arg2)
        {
            A a1 = DispatchTestHelper.CreateInstance(arg1);
            A a2 = DispatchTestHelper.CreateInstance(arg2);

            DispatchTestHelper check = new DispatchTestHelper();

            string expected = arg1 + arg2;
            Assert.AreEqual(expected, check.FF2(a1, a2));
        }
        public void Can_Dispatch_To_Methods_Taking_1_To_4_Parameters(bool is32BitPlatform)
        {
            Type type = typeof(DispatchTestHelper);

            DispatchTestHelper target = new DispatchTestHelper();

            Dispatcher mm1 = Dispatcher.Create(type, type.GetMethod("MM1"), is32BitPlatform);
            Dispatcher mm2 = Dispatcher.Create(type, type.GetMethod("MM2"), is32BitPlatform);
            Dispatcher mm3 = Dispatcher.Create(type, type.GetMethod("MM3"), is32BitPlatform);
            Dispatcher mm4 = Dispatcher.Create(type, type.GetMethod("MM4"), is32BitPlatform);

            Dispatcher ff1 = Dispatcher.Create(type, type.GetMethod("FF1"), is32BitPlatform);
            Dispatcher ff2 = Dispatcher.Create(type, type.GetMethod("FF2"), is32BitPlatform);
            Dispatcher ff3 = Dispatcher.Create(type, type.GetMethod("FF3"), is32BitPlatform);
            Dispatcher ff4 = Dispatcher.Create(type, type.GetMethod("FF4"), is32BitPlatform);

            DispatchResult result = mm1.Dispatch(target, new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("D", target.LastResult);

            result = mm2.Dispatch(target, new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DD", target.LastResult);

            result = mm3.Dispatch(target, new D(), new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DDD", target.LastResult);

            result = mm4.Dispatch(target, new D(), new D(), new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DDDD", target.LastResult);

            result = ff1.Dispatch(target, new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("D", result.ReturnValue);

            result = ff2.Dispatch(target, new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DD", result.ReturnValue);

            result = ff3.Dispatch(target, new D(), new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DDD", result.ReturnValue);

            result = ff4.Dispatch(target, new D(), new D(), new D(), new D());
            Assert.IsTrue(result.Success);
            Assert.AreEqual("DDDD", result.ReturnValue);
        }
        public void Combinatorial_Test_All_4_Argument_Dispatch(
            [Values("A", "B", "C", "D")] string arg1,
            [Values("A", "B", "C", "D")] string arg2,
            [Values("A", "B", "C", "D")] string arg3,
            [Values("A", "B", "C", "D")] string arg4)
        {
            A a1 = DispatchTestHelper.CreateInstance(arg1);
            A a2 = DispatchTestHelper.CreateInstance(arg2);
            A a3 = DispatchTestHelper.CreateInstance(arg3);
            A a4 = DispatchTestHelper.CreateInstance(arg4);

            DispatchTestHelper check = new DispatchTestHelper();

            string expected = arg1 + arg2 + arg3 + arg4;
            Assert.AreEqual(expected, check.FF4(a1, a2, a3, a4));
        }
        public void MultiMethod_Invoke_Is_Faster_Than_Cached_Dynamic_Invoke_To_Target_Method()
        {
            int count = 100000;

            DispatchTestHelper target = new DispatchTestHelper();

            D d1 = new D(), d2 = new D(), d3 = new D();

            MethodInfo method = typeof(DispatchTestHelper).GetMethod(
                "MM3", BindingFlags.Instance | BindingFlags.NonPublic,
                Type.DefaultBinder, new Type[] { typeof(D), typeof(D), typeof(D) }, null);

            DateTime start = DateTime.Now;
            for (int i = 0; i < count; ++i)
            {
                method.Invoke(target, new object[] { d1, d2, d3 });
            }
            double dynamicInvokeDuration = (DateTime.Now - start).TotalMilliseconds;

            start = DateTime.Now;
            for (int i = 0; i < count; ++i)
            {
                target.MM3(d1, d2, d3);
            }
            double multiMethodDuration = (DateTime.Now - start).TotalMilliseconds;

            Assert.Less(multiMethodDuration, dynamicInvokeDuration,
                string.Format("dynamic invoke={0} is faster than multi method invoke={1}",
                                dynamicInvokeDuration, multiMethodDuration));

            Console.WriteLine("multi method invoke={0} is faster than dynamic invoke={1}",
                                multiMethodDuration, dynamicInvokeDuration);
        }
        public void MultiMethod_Action_And_Function_Wrappers_Will_Dispatch_To_Correct_Method()
        {
            DispatchTestHelper check = new DispatchTestHelper();

            check.MM1(new D());
            Assert.AreEqual("D", check.LastResult);

            check.MM2(new D(), new D());
            Assert.AreEqual("DD", check.LastResult);

            check.MM3(new D(), new D(), new D());
            Assert.AreEqual("DDD", check.LastResult);

            check.MM4(new D(), new D(), new D(), new D());
            Assert.AreEqual("DDDD", check.LastResult);

            Assert.AreEqual("D", check.FF1(new D()));
            Assert.AreEqual("DD", check.FF2(new D(), new D()));
            Assert.AreEqual("DDD", check.FF3(new D(), new D(), new D()));
            Assert.AreEqual("DDDD", check.FF4(new D(), new D(), new D(), new D()));
        }