public PropertyWrapper(Type ownerType, PropertyInfo info, NanoLocation location, NanoState state, int constructorArg, string name)
            : base(ownerType, info, info.PropertyType, location, state, constructorArg, name)
        {
            Info = info;

            if (info.CanWrite)
            {
                writeAction = InvocationHelper.CreateSetDelegate(ownerType, info.PropertyType, info.SetMethod);
            }
            readFunc = InvocationHelper.CreateGetDelegate(ownerType, info.PropertyType, info.GetMethod);

            CanWrite = info.CanWrite;
            CanRead  = info.CanRead;

            IsPrivate = (!info.CanRead || info.GetMethod.IsPrivate) &&
                        (!info.CanWrite || info.SetMethod.IsPrivate);
        }
        public static void TestPerformance()
        {
            Test         test = new Test();
            PropertyInfo info = typeof(Test).GetProperty("A");

            const string TEST = "1";

            info.SetValue(test, TEST);
            Action <object, object> action = InvocationHelper.CreateSetDelegate(typeof(Test), typeof(string), info.SetMethod);
            MethodInfo method = info.SetMethod;

            action(test, TEST);

            Action <object, object> actionUntyped       = SetUntyped;
            Action <Test, string>   actionTyped         = SetUntyped;
            Action <Test, string>   actionLambdaTyped   = (target, arg) => target.A = arg;
            Action <object, object> actionLambdaUntyped = (target, arg) => ((Test)target).A = (string)arg;

            Action <Test, string> actionDelegate     = (Action <Test, string>)Delegate.CreateDelegate(typeof(Action <Test, string>), method);
            Func <object>         actionCreateLambda = CreateConstructorDelegate(typeof(Test));
            Func <object>         actionCreateEmit   = InvocationHelper.CreateConstructorDelegate(typeof(Test));
            ConstructorInfo       ctor = typeof(Test).GetConstructor(Type.EmptyTypes);

            ConstructorInfo         ctorString             = typeof(Test).GetConstructor(new Type[] { typeof(string) });
            Func <object[], object> actionCreateEmitString = InvocationHelper.CreateConstructorDelegate(typeof(Test), ctorString, ctorString.GetParameters());

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Performance test: Property set...");
            Console.ForegroundColor = ConsoleColor.Gray;

            WriteTestStart("PropertyInfo.SetValue");
            Stopwatch stopwatch = Stopwatch.StartNew();

            for (int i = 0; i < ITERATIONS; i++)
            {
                info.SetValue(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("MethodInfo.Invoke");
            stopwatch.Restart();
            object[] cache = { TEST };
            for (int i = 0; i < ITERATIONS; i++)
            {
                method.Invoke(test, cache);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("InvocationHelper.CreateSetDelegate");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                action(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("test.A = TEST");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                test.A = TEST;
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("SetTyped(Test test, string s)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                SetTyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("SetUntyped(object test, object s)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                SetUntyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("Action<Test, string>");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionTyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("Action<object, object>");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionUntyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("=> target.A = arg");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionLambdaTyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("=> ((Test)target).A = (string)arg");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionLambdaUntyped(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("Delegate.CreateDelegate");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionDelegate(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("Delegate.DynamicInvoke");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                action.DynamicInvoke(test, TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine();
            Console.WriteLine("Performance test: Object creation...");
            Console.ForegroundColor = ConsoleColor.Gray;

            WriteTestStart("Activator.Create");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                Activator.CreateInstance(typeof(Test));
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("CreateConstructorDelegate");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionCreateEmit();
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("() => new TResult()");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionCreateLambda();
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("ConstructorInfo.Invoke");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                ctor.Invoke(null);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("new Test()");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                // ReSharper disable once ObjectCreationAsStatement
                new Test();
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("Activator.Create (string)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                Activator.CreateInstance(typeof(Test), cache);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("CreateConstructorDelegate(string)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                actionCreateEmitString(cache);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("ConstructorInfo.Invoke(string)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                ctorString.Invoke(cache);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            WriteTestStart("new Test(string)");
            stopwatch.Restart();
            for (int i = 0; i < ITERATIONS; i++)
            {
                // ReSharper disable once ObjectCreationAsStatement
                new Test(TEST);
            }
            stopwatch.Stop();
            WriteTestFinish(stopwatch);

            Console.WriteLine("-- All done. Press <Enter> to continue.");
            Console.WriteLine();
        }