Click here to Skip to main content
15,896,063 members
Articles / Programming Languages / C#

Fast Dynamic Property/Field Accessors

Rate me:
Please Sign up or sign in to vote.
4.94/5 (35 votes)
4 Jul 20063 min read 190.8K   2.1K   137  
Fast run-time access to Property/Field values using the new (.NET 2.0) DynamicMethod class, and a very small amount of emitted IL code.
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace ReflectionTest
{
    public class MemberComparer<ObjectType> : IComparer<ObjectType>
    {
        private delegate int CompareDelegate(ObjectType x, ObjectType y);
        private CompareDelegate _compare;

        public MemberComparer(string memberName)
        {
            _compare = GetCompareDelegate(memberName);
        }

        public int Compare(ObjectType x, ObjectType y)
        {
            return _compare(x, y);
        }

        private CompareDelegate GetCompareDelegate(string memberName)
        {
            Type objectType = typeof(ObjectType);

            PropertyInfo pi = objectType.GetProperty(memberName);
            FieldInfo fi = objectType.GetField(memberName);
            Type memberType = null;
            bool isProperty = false;

            if (pi != null)
            {
                if (pi.GetGetMethod() != null)
                {
                    memberType = pi.PropertyType;
                    isProperty = true;
                }
                else
                    throw new Exception(String.Format(
                        "Property: '{0}' of Type: '{1}' does not have a Public Get accessor",
                        memberName, objectType.Name));
            }
            else if (fi != null)
                memberType = fi.FieldType;
            else
                throw new Exception(String.Format(
                    "Property: '{0}' of Type: '{1}' does not have a Public Get accessor",
                    memberName, objectType.Name));

            Type comparerType = typeof(Comparer<>).MakeGenericType(new Type[] { memberType });
            MethodInfo getDefaultMethod = comparerType.GetProperty("Default").GetGetMethod();
            MethodInfo compareMethod = getDefaultMethod.ReturnType.GetMethod("Compare");

            DynamicMethod dm = new DynamicMethod("Compare_" + memberName, typeof(int), new Type[] { objectType, objectType }, comparerType);
            ILGenerator il = dm.GetILGenerator();

            // Load Comparer<memberType>.Default onto the stack
            il.EmitCall(OpCodes.Call, getDefaultMethod, null);

            // Load the member from arg 0 onto the stack
            il.Emit(OpCodes.Ldarg_0);
            if (isProperty)
                il.EmitCall(OpCodes.Callvirt, pi.GetGetMethod(), null);
            else
                il.Emit(OpCodes.Ldfld);

            // Load the member from arg 1 onto the stack
            il.Emit(OpCodes.Ldarg_1);
            if (isProperty)
                il.EmitCall(OpCodes.Callvirt, pi.GetGetMethod(), null);
            else
                il.Emit(OpCodes.Ldfld);

            // Call the Compare method
            il.EmitCall(OpCodes.Callvirt, compareMethod, null);
            
            il.Emit(OpCodes.Ret);

            return (CompareDelegate)dm.CreateDelegate(typeof(CompareDelegate));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I am currently working as an Enterprise Architect at TicketsNow.com.

I have been designing and developing web/windows based software applications and utilities for 8+ years.

And here is a random picture of my dog. Wink | ;)

Comments and Discussions