public void MixinWorksAsExpected()
        {
            // reset a couple of static value counters that are used in the test in case the test runs multiple times
            MixinTarget.InstanceConstructorCalledCount = 0;
            MixinTarget.MixinImplementationConstructorCallCount = 0;

            // create the target object and an interface reference to it
            var target = new MixinTarget();
            var targetAsInterface = (IMixinDefinition)target;

            // show that static constructor worked as expected
            Assert.That(MixinTarget.NonMixinStaticValue, Is.EqualTo(34));
            Assert.That(MixinTarget.MixinStaticConstructorInitializedValue, Is.EqualTo(8978));

            // show that constructor worked as expected
            Assert.That(target.NonMixinValue, Is.EqualTo(532));
            Assert.That(target.MixinConstructorInitializedValue, Is.EqualTo(9843));

            // the called constructor chained into another constructor, so this should be two
            Assert.That(MixinTarget.InstanceConstructorCalledCount, Is.EqualTo(2));

            // even though two target instance constructors ran, the code for the mixin implementation constructor will have only run once
            Assert.That(MixinTarget.MixinImplementationConstructorCallCount, Is.EqualTo(1));

            // show that the interface is implemented
            Assert.That(target, Is.InstanceOf<IMixinDefinition>());

            // show that the existing property was untouched
            Assert.That(target.NonMixinProperty == 5);

            // show that the mixin property and field are available, including the explicitly implemented property
            Assert.That(target.Field, Is.EqualTo(0));
            Assert.That(target.Property, Is.EqualTo(int.MinValue));
            Assert.That(targetAsInterface.Property, Is.EqualTo(0));
            target.Field = 3209;
            Assert.That(target.Field, Is.EqualTo(3209));
            Assert.That(target.Property, Is.EqualTo(int.MinValue));
            Assert.That(targetAsInterface.Property, Is.EqualTo(3209));

            // show that a generic method call works
            var expectedValue = string.Format("Input has type {0} and string converted value 42", typeof(int).FullName);
            Assert.That(target.GenericMethod(42), Is.EqualTo(expectedValue));
            expectedValue = string.Format("Input has type {0} and string converted value 42", typeof(long).FullName);
            Assert.That(target.GenericMethod(42L), Is.EqualTo(expectedValue));
            expectedValue = string.Format("Input has type {0} and string converted value forty-two", typeof(string).FullName);
            Assert.That(target.GenericMethod("forty-two"), Is.EqualTo(expectedValue));

            // show that the event calls delegate as expected and that the method is called correctly
            var callCount = 0;
            EventHandler<UnhandledExceptionEventArgs> eventHandler = (sender, e) =>
                {
                    Assert.That(sender, Is.InstanceOf<MixinTarget>());
                    Assert.That(e.ExceptionObject, Has.Message.EqualTo("Funny"));
                    ++callCount;
                };

            target.AFunnyThingHappened += eventHandler;
            var list = target.Method(23, "one", "two", "three");
            Assert.That(callCount, Is.EqualTo(1));
            Assert.That(list, Is.EquivalentTo(new string[] { "23", "one", "two", "three" }));

            target.AFunnyThingHappened -= eventHandler;
            list = target.Method(32);
            Assert.That(callCount, Is.EqualTo(1));
            Assert.That(list, Is.EquivalentTo(new string[] { "32" }));

            // show that the delegate type and property are accessible and that a lambda expression was handled
            Assert.That(typeof(MixinTarget.SomeDelegateType).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(target.SomeDelegate("Lambda will return me"), Is.EqualTo("Lambda will return me"));

            // show that the flags enum acts as expected (including check for custom attribute)
            Assert.That(typeof(MixinTarget.Attributes).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(Attribute.IsDefined(typeof(MixinTarget.Attributes), typeof(FlagsAttribute)));
            var things = MixinTarget.Attributes.Thing2 | MixinTarget.Attributes.Thing5;
            Assert.That(things, Is.EqualTo((MixinTarget.Attributes)18));

            // show that the nested struct acts as expected
            Assert.That(typeof(MixinTarget.NestedStruct).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(typeof(MixinTarget.NestedStruct).IsValueType);
            var nestedStruct = new MixinTarget.NestedStruct();
            nestedStruct.Value = 60;
            Assert.That(nestedStruct.Value, Is.EqualTo(60));

            // show that the nested class acts as expected
            Assert.That(typeof(MixinTarget.NestedEventArgs).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(typeof(MixinTarget.NestedEventArgs).BaseType, Is.EqualTo(typeof(EventArgs)));
            var nestedEventArgs = new MixinTarget.NestedEventArgs();
            Assert.That(nestedEventArgs.Things, Is.EqualTo(MixinTarget.Attributes.Nothing));

            // show that the static field acts as expected
            MixinTarget.StaticField = 0;
            Assert.That(MixinTarget.StaticField, Is.EqualTo(0));
            MixinTarget.StaticField = 9;
            Assert.That(MixinTarget.StaticField, Is.EqualTo(9));

            // show that the static auto-property acts as expected
            MixinTarget.StaticProperty = 0;
            Assert.That(MixinTarget.StaticProperty, Is.EqualTo(0));
            MixinTarget.StaticProperty = 5648;
            Assert.That(MixinTarget.StaticProperty, Is.EqualTo(5648));

            // show that the static event calls delegate as expected and that the method is called correctly
            var staticCallCount = 0;
            EventHandler<MixinTarget.NestedEventArgs> staticEventHandler = (sender, e) =>
            {
                // note that the implementation code sends typeof(MixinImplementation), but that it is replaced by typeof(MixinTarget)
                Assert.That(sender, Is.EqualTo(typeof(MixinTarget)));
                Assert.That(e.Things, Is.EqualTo(MixinTarget.Attributes.Nothing));
                ++staticCallCount;
            };

            MixinTarget.NestedThingsHappened += staticEventHandler;
            var length = MixinTarget.StaticMethod("What you are is lovely");
            Assert.That(staticCallCount, Is.EqualTo(1));
            Assert.That(length, Is.EqualTo("What you are is lovely".Length));

            MixinTarget.NestedThingsHappened -= staticEventHandler;
            length = MixinTarget.StaticMethod(null);
            Assert.That(staticCallCount, Is.EqualTo(1));
            Assert.That(length, Is.EqualTo(0));

            // play around with a generic nested type
            var nestedTarget = new MixinTarget.NestedGenericType<int, string>(42, "forty-two");
            Assert.That(nestedTarget.Dee, Is.EqualTo(42));
            Assert.That(nestedTarget.Dum, Is.EqualTo("forty-two"));

            // more play, add in generic method with partially closed generic return type
            var wibblyWobbly = target.GetAThing(989);
            Assert.That(wibblyWobbly.Dee, Is.EqualTo("canned spam"));
            Assert.That(wibblyWobbly.Dum, Is.EqualTo(989));

            // show that a field that is initialized with an object initializer works
            Assert.That(target.FieldWithObjectInitializer.ObjectInitializableInt, Is.EqualTo(300));
        }
        public void MixinWorksAsExpected()
        {
            var target = new MixinTarget();
            var targetAsInterface = target as IMixinDefinition;

            // show that the interface is implemented
            Assert.That(target, Is.InstanceOf<IMixinDefinition>());

            // show that the existing property was untouched
            Assert.That(target.NonMixinProperty == 5);

            // show that the mixin property and field are available, including the explicitly implemented property
            Assert.That(target.Field, Is.EqualTo(0));
            Assert.That(target.Property, Is.EqualTo(int.MinValue));
            Assert.That(targetAsInterface.Property, Is.EqualTo(0));
            target.Field = 3209;
            Assert.That(target.Field, Is.EqualTo(3209));
            Assert.That(target.Property, Is.EqualTo(int.MinValue));
            Assert.That(targetAsInterface.Property, Is.EqualTo(3209));

            // show that the event calls delegate as expected and that the method is called correctly
            var callCount = 0;
            EventHandler<UnhandledExceptionEventArgs> eventHandler = (sender, e) =>
                {
                    Assert.That(sender, Is.InstanceOf<MixinTarget>());
                    Assert.That(e.ExceptionObject, Has.Message.EqualTo("Funny"));
                    ++callCount;
                };

            target.AFunnyThingHappened += eventHandler;
            var list = target.Method(23, "one", "two", "three");
            Assert.That(callCount, Is.EqualTo(1));
            Assert.That(list, Is.EquivalentTo(new string[] { "23", "one", "two", "three" }));

            target.AFunnyThingHappened -= eventHandler;
            list = target.Method(32);
            Assert.That(callCount, Is.EqualTo(1));
            Assert.That(list, Is.EquivalentTo(new string[] { "32" }));

            // show that the delegate type and property are accessible and that a lambda expression was handled
            Assert.That(typeof(MixinTarget.SomeDelegateType).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(target.SomeDelegate("Lambda will return me"), Is.EqualTo("Lambda will return me"));

            // show that the flags enum acts as expected (including check for custom attribute)
            Assert.That(typeof(MixinTarget.Attributes).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(Attribute.IsDefined(typeof(MixinTarget.Attributes), typeof(FlagsAttribute)));
            var things = MixinTarget.Attributes.Thing2 | MixinTarget.Attributes.Thing5;
            Assert.That(things, Is.EqualTo((MixinTarget.Attributes)18));

            // show that the nested struct acts as expected
            Assert.That(typeof(MixinTarget.NestedStruct).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(typeof(MixinTarget.NestedStruct).IsValueType);
            var nestedStruct = new MixinTarget.NestedStruct();
            nestedStruct.Value = 60;
            Assert.That(nestedStruct.Value, Is.EqualTo(60));

            // show that the nested class acts as expected
            Assert.That(typeof(MixinTarget.NestedEventArgs).DeclaringType, Is.EqualTo(typeof(MixinTarget)));
            Assert.That(typeof(MixinTarget.NestedEventArgs).BaseType, Is.EqualTo(typeof(EventArgs)));
            var nestedEventArgs = new MixinTarget.NestedEventArgs();
            Assert.That(nestedEventArgs.Things, Is.EqualTo(MixinTarget.Attributes.Nothing));

            // show that the static field acts as expected
            Assert.That(MixinTarget.StaticField, Is.EqualTo(0));
            MixinTarget.StaticField = 9;
            Assert.That(MixinTarget.StaticField, Is.EqualTo(9));

            // show that the static auto-property acts as expected
            Assert.That(MixinTarget.StaticProperty, Is.EqualTo(0));
            MixinTarget.StaticProperty = 5648;
            Assert.That(MixinTarget.StaticProperty, Is.EqualTo(5648));

            // show that the static event calls delegate as expected and that the method is called correctly
            var staticCallCount = 0;
            EventHandler<MixinTarget.NestedEventArgs> staticEventHandler = (sender, e) =>
            {
                // note that the implementation code sends typeof(MixinImplementation), but that it is replaced by typeof(MixinTarget)
                Assert.That(sender, Is.EqualTo(typeof(MixinTarget)));
                Assert.That(e.Things, Is.EqualTo(MixinTarget.Attributes.Nothing));
                ++staticCallCount;
            };

            MixinTarget.NestedThingsHappened += staticEventHandler;
            var length = MixinTarget.StaticMethod("What you are is lovely");
            Assert.That(staticCallCount, Is.EqualTo(1));
            Assert.That(length, Is.EqualTo("What you are is lovely".Length));

            MixinTarget.NestedThingsHappened -= staticEventHandler;
            length = MixinTarget.StaticMethod(null);
            Assert.That(staticCallCount, Is.EqualTo(1));
            Assert.That(length, Is.EqualTo(0));
        }