Rants, rambles, news and notes from another geek

Fun With Reflection

I was just on IM helping Kris Syverstad and Bob Brumfield with a little reflection problem. Along the way I asked him why he hadn’t prototyped his problem in NUnit… I guess they didn’ t think of it.

Anyway, here is an NUnit test that demonstrates a couple of points that they were fighting:

  1. When referencing a nested type, you have to use the plus sign between the parent class and the nested type
  2. The Invoke code that Bob posted wasn’t related to the problem.
  3. The Enum.Parse code that Bob posted wasn’t related to the problem

Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Reflection;
using NUnit.Framework;

namespace NestedTypeReflectionTest
{
	public class Foo
	{
		public enum Bar
		{
			Zero, One, Two, Three
		}

		public Bar TheBar
		{
			get { return _theBar; }
			set { _theBar = value; }
		}

		private Bar _theBar = Bar.Zero;
	}


	[TestFixture]
	public class TheTest
	{
		private Assembly _assembly;

		[SetUp]
		public void Setup()
		{
			// For this example we will use GetExecutingAssembly() but you
			// could also use Assembly.LoadFrom().
			_assembly = Assembly.GetExecutingAssembly();
		}

		[Test(Description="This test shows that a period doesn't work for nested types.")]
		[ExpectedException( typeof(TypeLoadException) )]
		public void PeriodThrows()
		{
			System.Type t = _assembly.GetType( "NestedTypeReflectionTest.Foo.Bar",  true, false );
		}

		[Test(Description="This test shows that a plus-sign does work for nested types.")]
		public void PlusDoesnt()
		{
			System.Type t = _assembly.GetType( "NestedTypeReflectionTest.Foo+Bar",  true, false );
			Assert.IsTrue( t.IsEnum );
		}

		[Test(Description="This test shows using the type with Invoke.")]
		public void Invoke()
		{
			System.Type t = _assembly.GetType( "NestedTypeReflectionTest.Foo+Bar",  true, false );
			object aValue = Enum.Parse( t, "One" );

			Foo foo = new Foo();
			BindingFlags flags = BindingFlags.Public | BindingFlags.Instance |  BindingFlags.SetProperty;
			foo.GetType().InvokeMember( "TheBar", flags, null, foo, new object[] { aValue });

			Assert.AreEqual( Foo.Bar.One, foo.TheBar );
		}
	}
}