public void TestAdaptation() { AdaptationTestBase t = GoInterface <AdaptationTestBase, AdaptationTests1> .ForceFrom(new AdaptationTests1()); t.Passthrough(1, 2, 3, "4"); int i; double d; object o; string s; Assert.That(t.Passthrough(out i, out d, out o, out s)); Assert.AreEqual(i, 1); Assert.AreEqual(d, 2); Assert.AreEqual(o, 3); Assert.AreEqual(s, "4"); Assert.That(t.Enlarge2int((short)-1, true)); Assert.That(t.Enlarge2int((ushort)0xFFFF, false)); Assert.That(t.Enlarge2uint((byte)0xFF)); Assert.That(t.Enlarge2uint((ushort)0xFFFF)); Assert.That(t.Enlarge2long(-1, true)); Assert.That(t.Enlarge2long((ushort)0xFFFF, false)); Assert.That(t.Enlarge2long((uint)0xFFFFFFFF, false)); Assert.That(t.Enlarge2float(1)); Assert.That(t.Enlarge2double(1)); Assert.That(t.Box((int)1)); Assert.That(t.Box(1.0)); Assert.That(t.Renamed()); t = GoInterface <AdaptationTestBase, AdaptationTests2> .ForceFrom(new AdaptationTests2()); t.Covariant(out i); Assert.That(i == 1); IDisposable idisp; t.Covariant(out idisp); Assert.That(idisp is MemoryStream); i = 0; Assert.That(t.Covariant2(ref i)); Assert.AreEqual(1, i); s = "1"; Assert.That(t.Invariant(ref s)); Assert.That(t.Invariant2(s)); Assert.That(t.Contravariant("1")); Assert.That(t.Contravariant(new MemoryStream())); Assert.That(t.Contravariant2(1)); i = 1; Assert.That(t.Contravariant3(ref i)); t.CovariantReturn(); Assert.That(t.CovariantReturn2() is bool); Assert.That(t.CovariantReturn3().ToString() == "true"); Assert.AreEqual(t.CovariantReturn4(), 1.0f); Assert.That(t.DroppedParam(1)); Assert.That(t.DroppedParam2()); Assert.That(t.DroppedParam3("1")); Assert.That(t.DefaultParam()); }
public void InheritanceTest() { object something = new FooB(); FooBase foo = GoInterface <FooBase> .From(something); Assert.That(foo.Foo() == "Foo"); Assert.That(foo.Bar() == "Bar"); Assert.That(foo.Baz(1) == "Baz"); Assert.That(((IBaz)foo).Baz(false) == "Baz"); Assert.That(foo.Baz() == "Baz"); something = new FooB(); IBaz baz = GoInterface <IBaz> .ForceFrom(something); Assert.That(((IBar)baz).Bar() == "Bar"); Assert.That(((IBar2)baz).Bar() == "Bar"); Assert.That(baz.Baz() == "Baz"); }
public void TestOverloading() { bool correct; int x = 1; object o; IOverloadingTest i = GoInterface <IOverloadingTest> .ForceFrom(new OverloadingTest()); Assert.That(i.MoreMatchingArgsAreBetter(1, 2)); Assert.That(i.MoreMatchingArgsAreBetter2(1, 2, 3)); Assert.That(i.MinimumSizeRequired(1)); Assert.That(i.MinimumSizeRequired2(1)); Assert.That(i.SignedIsBetter(1)); Assert.That(i.SignedIsBetter2(1)); Assert.That(i.UnsignedIsBetter(1)); Assert.That(i.UnsignedIsBetter2(1)); Assert.That(i.IntIsBetter(1)); Assert.That(i.FloatIsBetter(1)); Assert.That(i.FloatIsBetter2(1.0f)); Assert.That(i.MissingOutput(1)); Assert.That(i.MissingOutput2()); Assert.That(i.MissingInput(1, 2, 3)); Assert.That(i.MissingInput2(1, 2)); Assert.That(i.MissingInputAndOutput(1, 2, 3)); Assert.That(i.OptionalParam(1, 2)); Assert.That(i.OptionalParam2(1, 2, 3)); Assert.That(i.RefMismatch(1)); Assert.That(i.RefMismatch2(1)); Assert.That(i.RefMismatch3(ref x)); Assert.That(i.RefMismatch4(ref x)); Assert.That(i.RefMismatch5(1)); Assert.That(i.Contravariance("1")); Assert.That(i.Contravariance2(new MemoryStream())); Assert.That(i.Contravariance3(new MemoryStream())); Assert.That(i.Covariance(out x)); Assert.That(i.Covariance2(out o)); Assert.That(i.ReturnCovariance() is int && (int)i.ReturnCovariance() == 1); Assert.That(i.ReturnCovariance2() == 1.0f); i.ReturnCovariance3(out correct); Assert.That(correct); Assert.That(i.ChooseTheMatchingReturn(1)); Assert.That(i.IgnoreNonPublic(1)); }
public void TestAmbiguity() { IAmbig wrapped; try { wrapped = GoInterface <IAmbig> .From(new Ambig()); } catch (InvalidCastException e) { if (e.Message.Contains("4 ")) { return; // 4 ambiguous methods, just as expected } } wrapped = GoInterface <IAmbig> .ForceFrom(new Ambig()); int a = 0; Assert.ThrowsAny <MissingMethodException>(delegate() { wrapped.Strings("1", "2"); }); Assert.ThrowsAny <MissingMethodException>(delegate() { wrapped.RefMismatch(1, 2); }); Assert.ThrowsAny <MissingMethodException>(delegate() { wrapped.RefMismatch2(ref a, 2); }); Assert.ThrowsAny <MissingMethodException>(delegate() { wrapped.AmbigLarger(1); }); }
public static void DoBenchmark() { const int Iterations = 100000000; // Measure the time it takes to instantiate ten versions of // IReadOnlyList<T>. GoInterface is not able to create generic wrappers, // so every time you wrap the same generic type with a different type // parameter, GoInterface produces a completely separate wrapper. This // is not good for performance, but at least it makes it easy for our // benchmark to pick 10 "different" classes to create wrappers of. // // It is possible to wrap List<byte> not only as IReadOnlyList<byte> // but also as any larger integer type, such as IReadOnlyList<int>. // However, the wrapping of the GetEnumerator() methods doesn't work. // List<byte>.GetEnumerator() returns IEnumerator<byte>, but // IReadOnlyList<int>.GetEnumerator() returns IEnumerator<int>. There is // no implicit conversion from IEnumerator<byte> to IEnumerator<int>, // so GoInterface fails to wrap it. However, by using ForceFrom we get // around this limitation, which still allows us to use the indexer and // Count properties. If you call GetEnumerator(), though, you get a // MissingMethodException. // // Note that if you run this part of the benchmark twice without // exiting the program, the second time around it should take zero // milliseconds. And the benchmark generally runs more slowly right // after you reboot your computer. SimpleTimer timer = new SimpleTimer(); var dummy0 = GoInterface <IReadOnlyList <byte> > .ForceFrom(new List <byte>()); int firstOne = timer.Restart(); var dummy1 = GoInterface <IReadOnlyList <short> > .ForceFrom(new List <byte>()); var dummy2 = GoInterface <IReadOnlyList <ushort> > .ForceFrom(new List <byte>()); var dummy3 = GoInterface <IReadOnlyList <int> > .ForceFrom(new List <byte>()); var dummy4 = GoInterface <IReadOnlyList <uint> > .ForceFrom(new List <byte>()); var dummy5 = GoInterface <IReadOnlyList <long> > .ForceFrom(new List <byte>()); var dummy6 = GoInterface <IReadOnlyList <ulong> > .ForceFrom(new List <byte>()); var dummy7 = GoInterface <IReadOnlyList <float> > .ForceFrom(new List <byte>()); var dummy8 = GoInterface <IReadOnlyList <double> > .ForceFrom(new List <byte>()); var dummy9 = GoInterface <IReadOnlyList <object> > .ForceFrom(new List <byte>()); int nineMore = timer.Millisec; Console.WriteLine("First interface wrapped in {0}ms; nine more took {1}ms", firstOne, nineMore); // Second test: measure how long it takes to wrap the same List<int> // many times, using either GoInterface class. var list = new List <int>(); list.Add(0); list.Add(1); list.Add(2); list.Add(3); IList <int> ilist; IReadOnlyList <int> rolist; GoInterface <IReadOnlyList <int> > .From(list); // ignore first call timer.Restart(); int i = 0; do { ilist = list; // normal interface assignment is pretty much a no-op } while (++i < Iterations); int wrapTest0 = timer.Restart(); i = 0; do { rolist = GoInterface <IReadOnlyList <int> > .From(list); } while (++i < Iterations); int wrapTest1 = timer.Restart(); i = 0; do { rolist = GoInterface <IReadOnlyList <int>, List <int> > .From(list); } while (++i < Iterations); int wrapTest2 = timer.Restart(); Console.WriteLine("Wrapper creation speed ({0} million times):", Iterations / 1000000); Console.WriteLine("- {0} ms for normal .NET interfaces (no-op)", wrapTest0); Console.WriteLine("- {0} ms for GoInterface<IReadOnlyList<int>>.From()", wrapTest1); Console.WriteLine("- {0} ms for GoInterface<IReadOnlyList<int>,List<int>>.From()", wrapTest2); int total0 = 0, total1 = 0, total2 = 0; timer.Restart(); for (i = 0; i < Iterations; i++) { total0 += list[i & 3]; } int callTestDirectCall = timer.Restart(); for (i = 0; i < Iterations; i++) { total1 += ilist[i & 3]; } int callTestNormalInterface = timer.Restart(); for (i = 0; i < Iterations; i++) { total2 += rolist[i & 3]; } int callTestGoInterface = timer.Restart(); Debug.Assert(total0 == total1 && total1 == total2); Console.WriteLine("Time to call indexer of List<int> ({0} million times):", Iterations / 1000000); Console.WriteLine("- {0} ms for direct calls (not through an interface)", callTestDirectCall); Console.WriteLine("- {0} ms through IList<int> (normal interface)", callTestNormalInterface); Console.WriteLine("- {0} ms through IReadOnlyList<int> (GoInterface)", callTestGoInterface); }