Thursday, April 23, 2015

Reflection in C#, Part 1

Intro

Reflection is a technology whereby you can view and modify the structure and behavior of a program at runtime. This general definition always seemed a bit vague to me, so picture this: You have a class, and for whatever reason you want the user to be able to select a property of your object from a dropdown, and type in a new value for the property in a textbox. You could manually populate your dropdown with the property names and have a big switch statement to set the value, but reflection would make this much easier by allowing you to, at runtime, discover the names of the properties and set their values. Nifty! I've personally used reflection for custom serialization (If you've heard of and used the TurboTags 2.0 format then you've used my reflection), and I've used it for a custom storage system that works a lot like Entity Framework. Well, now that I've tooted my own reflection horn let's get down to shiny and highly reflective brass tacks.


Note: Samples are VS2013 Community edition, .Net 4.5. Here is the sample project if you want to play along.

 

What can Reflection Do?

  • List Classes in Assembly - You can get a listing of the classes within an assembly.
  • Create Instance of Classes - You can create an instance of one of them thar classes that you found.
  • List Properties - Need a listing of the properties of the class? Reflection has you covered.
  • Get and set property value - Ooh, and you can modify those properties too!
  • List Methods - Once you've listed the properties of a class, it's easy to list the methods.
  • Execute Methods - Executing the methods with reflection is simple once you've found them.
  • And More! - Yay more! You can get attributes and other things too.
Let's dig into some specifics. I doubt we'll cover all of them this week, but let's give it the ol' college try.

List Classes in Assembly

I've created a Windows Forms app for demonstration purposes. Let's start by listing all the classes in an assembly. The first thing we need to do, after creating the solution of course, is add a reference to the System.Reflection assembly. This is where we get all the reflection junk. Now we're going to, in the Form_Load event handler, populate a dropdownlist with the classes of our current assembly:

        private void MainForm_Load(object sender, EventArgs e)
        {
            var a = Assembly.GetExecutingAssembly();
            ListClassesEntry.Items.AddRange(a.GetTypes());
        }


Getting a reference to the current assembly is easy with reflection. We accomplish the task above by calling Assembly.GetExecutingAssembly. The next line shows how to get all the classes contained within the assembly. In our case we come up with 4 distinct classes: BlogReflection.MainForm, BlogReflection.Program, BlogReflection.Properties.Resources, and BlogReflection.Properties.Settings. This is a nice, small, manageable list. Yay!

Create An Instance of a Class

Now that we have a list of classes within our assembly, let's create an instance of the selected class when the user selects a Type from the DropDownList:

        private void ListClassesEntry_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!String.IsNullOrWhiteSpace(ListClassesEntry.SelectedItem.ToString()))
            {
                var assembly = Assembly.GetExecutingAssembly();
                var formType = assembly.GetType(ListClassesEntry.SelectedItem.ToString());
                var constructor = formType.GetConstructor(new Type[] { });
                var instance = constructor.Invoke(new Object[] { });
            }
        }


Another pretty simple method. The key part here is the call to GetConstructor and then the call to Invoke. GetConstructor, in this form, will find the constructor that accepts parameters as specified by the Type[] type array parameter. In our case we passed in an  empty array of type Type, so we want a parameterless constructor. The next line, Invoke, calls the constructor method passing in another empty array of parameters. So in essence we first find the parameterless constructor of the selected type, and we then invoke the parameterless constructor of the type. Neato! Tip: This method bombs horribly if the type you select, with the DropDownList, doesn't have a parameterless constructor. Oh well, nothing's perfect. Figure out how to get around that on your own :)

We're Done!

Hey Pete, you didn't talk about all the other cool stuff Reflection can do! You're right, what can I say; I'm lazy. We'll cover some more parts of reflection next week.

What's Next?

Figure out how you can call a constructor that has parameters. If you'd like to, you can also skip ahead to next week's topic by figuring out how to find and execute methods as well as find and get/set property values.


Resources

C# Reflection

1 comment:

  1. Thanks a lot for sharing this amazing knowledge with us. This site is fantastic. I always find great knowledge from it. Antigen Covid Test

    ReplyDelete