public void TypeChecker(bool derivedTypes)
        {
            // Arrange
            var matchObject      = new ChildClass1();
            var noMatch          = new ChildClass2();
            var sameTypeCheck    = ReflectionTool.TypePredicate(typeof(ChildClass1), derivedTypes);
            var derivedTypeCheck = ReflectionTool.TypePredicate(typeof(BaseClass), derivedTypes);

            // Act
            var isSame    = sameTypeCheck(matchObject);
            var different = sameTypeCheck(noMatch);
            var isDerived = derivedTypeCheck(matchObject);

            // Assert
            Assert.IsTrue(isSame, "Comparison for the same type must always return true");
            Assert.IsFalse(different, "Comparison for incompatible types must return false");
            Assert.AreEqual(derivedTypes, isDerived, "Comparison for derived types should only work if configured that way");
        }
        //[Test]
        public void PropertyAccessorIsFaster()
        {
            // Arrange
            var childType = typeof(ChildClass1);
            var child1    = new ChildClass1();
            var child2    = new ChildClass1();
            var prop      = childType.GetProperty(nameof(ChildClass1.Foo));
            var accessor  = ReflectionTool.PropertyAccessor <BaseClass, int>(prop);
            // Run once for JIT
            var value = prop.GetValue(new ChildClass1());

            prop.SetValue(new ChildClass1(), 1);
            accessor.ReadProperty(new ChildClass1());
            accessor.WriteProperty(new ChildClass1(), 1);

            // Act
            var stopWatch = new Stopwatch();

            stopWatch.Start();
            for (int i = 0; i < 100; i++)
            {
                var next = (int)prop.GetValue(child1) + i;
                prop.SetValue(child1, next);
            }
            stopWatch.Stop();
            var reflection = stopWatch.ElapsedTicks;

            stopWatch.Restart();
            for (int i = 0; i < 100; i++)
            {
                var next = accessor.ReadProperty(child2) + i;
                accessor.WriteProperty(child2, next);
            }
            stopWatch.Stop();
            var accesor = stopWatch.ElapsedTicks;

            // Asser
            Assert.AreEqual(child1.Foo, child2.Foo);
            Assert.Less(accesor, reflection, "Accessor should be faster");
        }
        public void PropertyAccessor()
        {
            // Arrange
            var childType = typeof(ChildClass1);
            var prop      = childType.GetProperty(nameof(ChildClass1.Foo));

            // Act
            var accessor0 = ReflectionTool.PropertyAccessor(prop);
            var child0    = new ChildClass1();

            accessor0.WriteProperty(child0, 42);
            var accessor1 = ReflectionTool.PropertyAccessor <IBaseInterface>(prop);
            var child1    = new ChildClass1();

            accessor1.WriteProperty(child1, 42);
            var child2 = new ChildClass1();

            accessor1.WriteProperty(child2, 42L);
            var accessor2 = ReflectionTool.PropertyAccessor <BaseClass, long>(prop);
            var child3    = new ChildClass1();

            accessor2.WriteProperty(child3, 42L);
            var accessor3 = ReflectionTool.PropertyAccessor <BaseClass, short>(prop);
            var child4    = new ChildClass1();

            accessor3.WriteProperty(child4, 42);
            var accessor4 = ReflectionTool.PropertyAccessor <ChildClass1, int>(prop);
            var child5    = new ChildClass1();

            accessor4.WriteProperty(child5, 42);

            // Assert
            Assert.AreEqual(42, child0.Foo);
            Assert.AreEqual(42, child1.Foo);
            Assert.AreEqual(42, child2.Foo);
            Assert.AreEqual(42, child3.Foo);
            Assert.AreEqual(42, child4.Foo);
            Assert.AreEqual(42, child5.Foo);
        }