Simple .Net Reflection Utility Class

I find that at least once in a project, I am digging into the System.Reflection msdn help page trying to identify what method calls and BindingFlags I need to make to lookup a field, property or method on an object and invoke it. The last time I did this; I took the code and moved it into a class.

Another advantage that I found of using the Reflector class is that it makes my code a little more more readable.  It is immediately obvious that

Reflector.StaticGetProperty(typeof(Cusomter), "FullName") 

is retrieveing the value of the static property FullName on the Customer type.  Compare this to

typeof(Customer).InvokeMember("FullName", BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty, null, null, null)

and to a lesser extent

typeof(Cusomter).GetProperty("FullName", BindingFlags.Public | BindingFlags.Static)
 

Download code

Here is the sample usage and below that the utility class …

class Program
{
    static void Main(string[] args)
    {
        object matt = Reflector.CreateInstance(typeof(Person), "Matt", "Berseth");

        //  Print the property values
        Console.WriteLine(Reflector.GetProperty(matt, "FirstName"));
        Console.WriteLine(Reflector.GetProperty(matt, "LastName"));

        //  Print the field values
        Console.WriteLine(Reflector.GetField(matt, "_firstName"));
        Console.WriteLine(Reflector.GetField(matt, "_lastName"));

        //  Set the property value
        Reflector.SetProperty(matt, "FirstName", "New First Name");
        Console.WriteLine(Reflector.GetProperty(matt, "FirstName"));

        //  Invoke a method
        Console.WriteLine(Reflector.CallMethod(matt, "FullName"));
    }
}

/// <summary>
/// 
/// </summary>
public class Person
{
    /// <summary>
    /// 
    /// </summary>
    private string _firstName;
    /// <summary>
    /// 
    /// </summary>
    private string _lastName;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="firstName"></param>
    /// <param name="lastName"></param>
    public Person(string firstName, string lastName)
    {
        this._firstName = firstName;
        this._lastName = lastName;
    }

    /// <summary>
    /// 
    /// </summary>
    public string FirstName
    {
        get { return this._firstName; }
        set { this._firstName = value; }
    }

    /// <summary>
    /// 
    /// </summary>
    public string LastName
    {
        get { return this._lastName; }
        set { this._lastName = value; }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public virtual string FullName()
    {
        return string.Format("{0} {1}", this.FirstName, this.LastName);
    }
}

 

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace ReflectionFacade
{
    /// <summary>
    /// Utility class for easy access to common System.Reflection features
    /// </summary>
    public static class Reflector
    {
        private const BindingFlags CommonFlags = BindingFlags.Public | BindingFlags.NonPublic;

        /// <summary>
        /// 
        /// </summary>
        public static object CreateInstance(Type type, params object[] args)
        {
            return Reflector.InvokeMember(
                type, null, null, 
                Reflector.CommonFlags | BindingFlags.CreateInstance | BindingFlags.Instance, args);
        }

        /// <summary>
        /// 
        /// </summary>
        public static void SetField(object target, string fieldName, object value)
        {
            Reflector.InvokeMember(
                target.GetType(), target, fieldName, 
                Reflector.CommonFlags | BindingFlags.SetField | BindingFlags.Instance, value);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object GetField(object target, string fieldName)
        {
            return Reflector.InvokeMember(
                target.GetType(), target, fieldName, 
                Reflector.CommonFlags | BindingFlags.GetField | BindingFlags.Instance);
        }

        /// <summary>
        /// 
        /// </summary>
        public static void SetProperty(object target, string propertyName, object value)
        {
            Reflector.InvokeMember(
                target.GetType(), target, propertyName, 
                Reflector.CommonFlags | BindingFlags.SetProperty | BindingFlags.Instance, value);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object GetProperty(object target, string propertyName)
        {
            return Reflector.InvokeMember(
                target.GetType(), target, propertyName, 
                Reflector.CommonFlags | BindingFlags.GetProperty | BindingFlags.Instance);
        }

        /// <summary>
        /// 
        /// </summary>
        public static void StaticSetField(Type type, string fieldName, object value)
        {
            Reflector.InvokeMember(
                type, null, fieldName, 
                Reflector.CommonFlags | BindingFlags.SetField | BindingFlags.Static, value);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object StaticGetField(Type type, string fieldName)
        {
            return Reflector.InvokeMember(
                type, null, fieldName, 
                Reflector.CommonFlags | BindingFlags.GetField | BindingFlags.Static);
        }

        /// <summary>
        /// 
        /// </summary>
        public static void StaticSetProperty(Type type, string propertyName, object value)
        {
            Reflector.InvokeMember(
                type, null, propertyName, 
                Reflector.CommonFlags | BindingFlags.SetProperty | BindingFlags.Static, value);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object StaticGetProperty(Type type, string propertyName)
        {
            return Reflector.InvokeMember(
                type, null, propertyName, 
                Reflector.CommonFlags | BindingFlags.GetProperty | BindingFlags.Static);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object CallMethod(object target, string methodName, params object[] args)
        {
            return Reflector.InvokeMember(
                target.GetType(), target, methodName, 
                Reflector.CommonFlags | BindingFlags.InvokeMethod | BindingFlags.Instance, args);
        }

        /// <summary>
        /// 
        /// </summary>
        public static object StaticCallMethod(Type type, string memberName, params object[] args)
        {
            return Reflector.InvokeMember(
                type, null, null, 
                Reflector.CommonFlags | BindingFlags.InvokeMethod | BindingFlags.Static, args);
        }

        /// <summary>
        /// 
        /// </summary>
        private static object InvokeMember(
            Type type, object target, string memberName, BindingFlags flags, params object[] args)
        {
            return type.InvokeMember(memberName, flags, null, target, args);
        }
    }
}

 


TrackBack

TrackBack URL for this entry:
http://mattberseth.com/blog-mt/mt-tb.fcgi/1

Listed below are links to weblogs that reference Simple .Net Reflection Utility Class:

» Simple .Net Reflection Utility Class from DotNetKicks.com
You've been kicked (a good thing) - Trackback from DotNetKicks.com [Read More]

Comments


Posted by: Max on May 17, 2007 12:00 AM

you should be very careful with reflection. Performance of GetProperty and GetMethod methods is really poor. I would recomend to precache memberName to PropertyInfo (MethodInfo) pairs in dictionary.

You are right on Max. For completeness, I will post a follow-up comparing the relative performance of this utility class versus, caching, versus invoking the members directly.

Posted by: Jason on May 19, 2007 12:00 AM

I believe including BindingFlags.Public in the flags for any reflection call is redundant.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

Consulting Services

Yep - I also offer consulting services. And heck, I'll do just about anything. If you enjoy my blog just drop me an email describing the work you need done.

Recent Comments

  • Jason wrote: I believe including BindingFlags.Public in the flags for any reflection call is redundant. ...
  • Max wrote: you should be very careful with reflection. Performance of GetProperty and GetMethod methods is real...
  • Matt Berseth wrote: You are right on Max. For completeness, I will post a follow-up comparing the relative performance ...