|
|
A Little More To Reflect OnDiscovering the Details About Types | | I wrote a brief article to System.Reflection that showed you how to generically identify every member of a class (I've included that piece in the code snippet below just in case you aren't familiar with it). Anyway, there's a whole lot more to Reflection that simply finding out all of its memebers. There are so many things you can Reflect that it's really amazing. Many of the properties simply return true or false. So, myType.IsPrimitive returns a boolean indicating if the type in question is a .NET Primitive type or not. There are other ones like IsSealed, IsPublic..... and many others. Then there are many that return every instance of something, like all of the Properties or all of the events of a class. Since a Type can be an string, int, enum, Foo, or anything else, many things may not be relevant in a given context, like why would you need to know if an int is Primitive..you should know that already. Remember though that Reflection gets all of its power from being able to discern things at Runtime! Anyway, I walk through some of the common methods and properties..there are many more but I think this covers a lot of the commonly used ones. I'd encourage you to fill in RatesManager.Utility with the namespace and class you created and then use intellisense to learn a little more about Reflection and the class you just wrote...
/Get Type information for Utility, a class I just whipped
//up for demonstration purposes
Type myType = Type.GetType("RatesManager.Utility");
//Write out fully qualified class name
Debug.WriteLine(myType.FullName);
//What is its memeber type
Debug.WriteLine(myType.MemberType.ToString());
//Very Cool feature, let's you determine at Runtime if you
//are dealing with a value type or reference type
Debug.WriteLine(myType.IsValueType.ToString());
//Will tell you if it's passed by ref....
//ByVal is .NET's default, so you only need to check true
//or false
Debug.WriteLine(myType.IsByRef.ToString());
//Will show RatesManager
Debug.WriteLine(myType.Namespace);
//RatesManager.exe ..The Executing module
//not the same as module in VB.NET
Debug.WriteLine(myType.Module.Name);
//Tells if you can inerhit from this class
//false in this instance
Debug.WriteLine(myType.IsSealed.ToString());
//Tells if it is a Primitive Type or not
Debug.WriteLine(myType.IsPrimitive.ToString());
//Tells if this type is an enum
Debug.WriteLine(myType.IsEnum.ToString());
//Will return all class members
foreach(MemberInfo mi in myType.GetMembers())
{
Debug.WriteLine(mi.Name);
}
//Will get all of the public fields
foreach(MemberInfo mi in myType.GetFields())
{
Debug.WriteLine(mi.Name);
}
//will print all of the properties of the class
foreach(MemberInfo mi in myType.GetProperties())
{
Debug.WriteLine(mi.Name);
}
//Will print all of the events for the class
foreach(MemberInfo mi in myType.GetEvents())
{
Debug.WriteLine(mi.Name);
}
| Now, here is what the disassembled code looks like (below). Anyway, you can see that it's pretty straightforward behind the scenes. The Debug.Writeline is pretty much irrelevant to how Reflection works, but as I mentioned in my other article, it helps to see what's happening. Once again, if you look through the instructions, everything is pretty much what you'd expect. The 'IsX' methods are all instance methods and Boolean. Big shock there. The strings are all strings and the MemberInfo variables that all return 0 or more values are all declared as Arrays. So, nothing magic is happening behind the scenes with Reflection. (I've used Environment and Reflection as my first two classes to go show the disassembly b/c they are so straightforward, my next article will start disassembling some VB.NET code with Default Parameters and some other things that aren't supported in C# ---- that's where IL gets to be really interesting!
//I've cut about half of the IL out b/c it's overkill...
.method private hidebysig instance void Form1_Load(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// Code size 301 (0x12d)
.maxstack 2
.locals init ([0] class [mscorlib]System.Type myType,
[1] class [mscorlib]System.Reflection.MemberInfo mi,
[2] class [mscorlib]System.Reflection.MemberInfo V_2,
[3] class [mscorlib]System.Reflection.MemberInfo V_3,
[4] class [mscorlib]System.Reflection.MemberInfo V_4,
[5] bool CS$00000002$00000000,
[6] bool CS$00000002$00000001,
[7] class [mscorlib]System.Reflection.MemberInfo[] CS$00000007$00000002,
[8] int32 CS$00000008$00000003,
[9] class [mscorlib]System.Reflection.FieldInfo[] CS$00000007$00000004,
[10] int32 CS$00000008$00000005,
[11] class [mscorlib]System.Reflection.PropertyInfo[] CS$00000007$00000006,
[12] int32 CS$00000008$00000007,
[13] class [mscorlib]System.Reflection.EventInfo[] CS$00000007$00000008,
[14] int32 CS$00000008$00000009)
IL_0000: ldstr "RatesManager.Utility"
IL_0005: call class [mscorlib]System.Type [mscorlib]System.Type::GetType(string)
IL_000a: stloc.0
IL_000b: ldloc.0
IL_000c: callvirt instance string [mscorlib]System.Type::get_FullName()
IL_0011: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_0016: ldloc.0
IL_0017: callvirt instance valuetype [mscorlib]System.Reflection.MemberTypes [mscorlib]System.Reflection.MemberInfo::get_MemberType()
IL_001c: box [mscorlib]System.Reflection.MemberTypes
IL_0021: call instance string [mscorlib]System.Enum::ToString()
IL_0026: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_002b: ldloc.0
IL_002c: callvirt instance bool [mscorlib]System.Type::get_IsValueType()
IL_0031: stloc.s CS$00000002$00000000
IL_0033: ldloca.s CS$00000002$00000000
IL_0049: call instance string [mscorlib]System.Boolean::ToString()
IL_004e: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_0053: ldloc.0
IL_0054: callvirt instance string [mscorlib]System.Type::get_Namespace()
IL_0059: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_005e: ldloc.0
IL_005f: callvirt instance class [mscorlib]System.Reflection.Module [mscorlib]System.Type::get_Module()
IL_0064: callvirt instance string [mscorlib]System.Reflection.Module::get_Name()
IL_0069: call void [System]System.Diagnostics.Debug::WriteLine(string)
IL_006e: ldloc.0
IL_006f: callvirt instance class [mscorlib]System.Reflection.MemberInfo[] [mscorlib]System.Type::GetMembers()
IL_0074: stloc.s CS$00000007$00000002
IL_0076: ldc.i4.0
IL_0077: stloc.s CS$00000008$00000003
IL_0079: br.s IL_0092
IL_007b: ldloc.s CS$00000007$00000002
IL_007d: ldloc.s CS$00000008$00000003
IL_0090: stloc.s CS$00000008$00000003
IL_0092: ldloc.s CS$00000008$00000003
IL_0094: ldloc.s CS$00000007$00000002
IL_0096: ldlen
IL_0097: conv.i4
IL_0098: blt.s IL_007b
} // end of method Form1::Form1_Load | |
|