public void Setup()
        {
            var ctorArgTypes = new[] { typeof(IFoo) };
            var type         = typeof(Foo);
            var constructor  = _ctorInfo = type.GetConstructor(ctorArgTypes);

            if (constructor == null)
            {
                throw new Exception("Failed to get the ctor.");
            }

            //IL_0000: ldarg.0      // this
            //IL_0001: ldfld        class Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks::_foo
            //IL_0006: newobj instance void Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/Foo::.ctor(class Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo)
            //IL_000b: pop
            //IL_000c: ret

            // generate a dynamic method
            //
            // ldarg.0      // obj0
            // newobj instance void [Umbraco.Tests.Benchmarks]Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks / Foo::.ctor(class [Umbraco.Tests.Benchmarks] Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo)
            // ret

            var meth = new DynamicMethod(string.Empty, typeof(IFoo), ctorArgTypes, type.Module, true);
            var gen  = meth.GetILGenerator();

            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Newobj, constructor);
            gen.Emit(OpCodes.Ret);
            _dynamicMethod = (Func <IFoo, IFoo>)meth.CreateDelegate(typeof(Func <IFoo, IFoo>));

            // generate a compiled expression
            //
            // ldarg.0      // content
            // newobj instance void [Umbraco.Tests.Benchmarks]Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks / Foo::.ctor(class [Umbraco.Tests.Benchmarks] Umbraco.Tests.Benchmarks.CtorInvokeBenchmarks/IFoo)
            // ret

            var exprArg = Expression.Parameter(typeof(IFoo), "content");
            var exprNew = Expression.New(constructor, exprArg);
            var expr    = Expression.Lambda <Func <IFoo, IFoo> >(exprNew, exprArg);

            _expressionMethod = expr.Compile();

            // create a dynamic assembly
            // dump to disk so we can review IL code with eg DotPeek

            var assemblyName = new AssemblyName("Umbraco.Tests.Benchmarks.IL");
            var assembly     = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
            var module       = assembly.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll");
            var typeBuilder  = module.DefineType("CtorInvoke", TypeAttributes.Public | TypeAttributes.Abstract);

            var expressionMethodBuilder = typeBuilder.DefineMethod("ExpressionCtor",
                                                                   MethodAttributes.Public | MethodAttributes.Static, // CompileToMethod requires a static method
                                                                   typeof(IFoo), ctorArgTypes);

            expr.CompileToMethod(expressionMethodBuilder);

            var dynamicMethodBuilder = typeBuilder.DefineMethod("DynamicCtor",
                                                                MethodAttributes.Public | MethodAttributes.Static,
                                                                typeof(IFoo), ctorArgTypes);

            gen = dynamicMethodBuilder.GetILGenerator();
            gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Newobj, constructor);
            gen.Emit(OpCodes.Ret);
            meth.CreateDelegate(typeof(Func <IFoo, IFoo>));

            var btype = typeBuilder.CreateType(); // need to build before saving

            assembly.Save("Umbraco.Tests.Benchmarks.IL.dll");

            // at that point,
            //   _dynamicMethod is 2x slower than direct ctor
            //   _expressionMethod is 6x slower than direct ctor
            // which is weird as inspecting the assembly IL shows that they are generated
            // exactly the same, and yet it is confirmed eg by https://stackoverflow.com/questions/4211418
            //
            // not sure why exactly
            // see https://stackoverflow.com/questions/13431573
            // see http://mattwarren.org/2017/01/25/How-do-.NET-delegates-work/#different-types-of-delegates
            //
            // note that all the benchmark methods have the very same IL code so it's
            // really the 'callvirt ...' that ends up doing different things
            //
            // more readings:
            // http://byterot.blogspot.dk/2012/05/performance-comparison-of-code.html
            // https://stackoverflow.com/questions/1296683
            // https://stackoverflow.com/questions/44239127
            // that last one points to
            // https://blogs.msdn.microsoft.com/seteplia/2017/02/01/dissecting-the-new-constraint-in-c-a-perfect-example-of-a-leaky-abstraction/
            // which reads ... "Expression.Compile creates a DynamicMethod and associates it with an anonymous assembly
            // to run it in a sandboxed environment. This makes it safe for a dynamic method to be emitted and executed
            // by partially trusted code but adds some run-time overhead."
            // and, turning things into a delegate (below) removes that overhead...

            // turning it into a delegate seems cool, _expressionMethod2 is ~ _dynamicMethod
            _expressionMethod2 = (Func <IFoo, IFoo>)Delegate.CreateDelegate(typeof(Func <IFoo, IFoo>), btype.GetMethod("ExpressionCtor"));

            // nope, this won't work, throws an ArgumentException because 'MethodInfo must be a MethodInfo object'
            // and here it's of type System.Reflection.Emit.DynamicMethod+RTDynamicMethod - whereas the btype one is ok
            // so, the dynamic assembly step is required
            //
            //_expressionMethod3 = (Func<IFoo, IFoo>) Delegate.CreateDelegate(typeof (Func<IFoo, IFoo>), _expressionMethod.Method);

            // but, our utilities know how to do it!
            _expressionMethod3 = ReflectionUtilities.CompileToDelegate(expr);
            _expressionMethod4 = ReflectionUtilities.GetCtor <Foo, IFoo>();

            // however, unfortunately, the generated "compiled to delegate" code cannot access private stuff :(

            _emittedCtor = ReflectionUtilities.EmitConstructor <Func <IFoo, Foo> >();
        }