Sunday, May 3, 2015

Reflection in C#, Part 2

Intro

This here posting is part 2 of 2 in our series on Reflection in C#. Review Part 1 first to see what we started with. All done? OK cool. You wouldn't lie to me about that would you? Nah of course not, I trust you. On with the blog! We saw in the last post how we can list the classes in an assembly and how to create an instance of a class through reflection. Useful stuff. We have more work to go though so let's get it on! Or something.


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

What Else Can Reflection Do?

Other than listing the classes in an assembly and creating an instance of a class, what else can we do with reflection? We can list and modify property values, and we can list and execute methods. There's a little more too, but those 4 things are what I want to cover right now. So, let's see some of it in action!

First we have here a class that doesn't do much. It's got a single string property that we're going to play with, and a constructor that sets a default value for said property.

namespace BlogReflection
{
    public class DummyClass
    {
        public string AValue { get; set; }

        public DummyClass()
        {
            AValue = "timmeh!";
        }
    }
}


This class by itself doesn't illustrate anything other than I can type the word Dummy. So, have a look-see at this second class:

using System;
using System.Reflection;
using System.Windows.Forms;

namespace BlogReflection
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

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

        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[] { });
                var methods = formType.GetMethods();
                string methodNames = "METHOD NAMES: ";
                foreach (var method in methods)
                    methodNames += method.Name + ",";
                MessageBox.Show(methodNames);
                var toStringMethod = formType.GetMethod("ToString");
                MessageBox.Show("ToString() : " + (string)toStringMethod.Invoke(instance, new Object[] { }));
                var properties = formType.GetProperties();
                string propertyNames = "PROPERTY NAMES: ";
                foreach (var property in properties)
                    propertyNames += property.Name + ",";
                MessageBox.Show(propertyNames);
                var selectedProperty = formType.GetProperty("AValue");
                MessageBox.Show("AValue: " + selectedProperty.GetValue(instance).ToString());
                selectedProperty.SetValue(instance, "some silly value");
                MessageBox.Show("AValue: " + selectedProperty.GetValue(instance).ToString());
            }
        }
    }
}


This class does 4 important things that illustrate the functionality of reflection:
  1. Find all methods of a class: Line 28, where we call GetMethods(), returns an array of methods in the class DummyClass.
  2. Execute a method: Line 34 uses Invoke, passing it a reference to the ToString method to call it. 
  3. Find all properties of a class: Line 35 calls GetProperties, which returns an array of all the properties of our class DummyClass.
  4. Get and set a property value: Lines 41 and 43 retrieve the value of the property AValue, while line 42 sets the value of the property AValue.

Not really all that complicated is it? Reflection sounds mean and nasty, but once you get into it it's as easy as theoretical physics. Or pie. Mmmm, pie.


Resources

C# Reflection

No comments:

Post a Comment