CSharpFeeds - All your C# feeds in one place.

Sponsors

Saturday, January 19, 2008

Evil Extension method

by gavin via elephantsintheroom.org on 1/19/2008 1:40:03 AM

The Evil method (+ 1 overload and a MemberInfo extension), below, allows traversal of an object graph by string. It works on properties, fields and methods that take no parameters or indexers.
 
usage: string s = person.Evil("Home.Postcode.ToString");
 
static class ObjectExtension
   {
       public static object Evil(this object target
           , string s)
       {
           return target.Evil(s, '.', '\\', '/', ',');
       }
       public static object Evil(this object target
           , string s, params  
           char[] separator)
       {
           var array = s.Split(separator,
               StringSplitOptions.RemoveEmptyEntries);
           if (array.Length == 0)
               return target;
           var members = target.GetType().GetMember
               (array.First().Trim());
           if (members.Length == 0)
               return null;
           var ret = members.First().GetValue(target);
           if (array.Length > 1)//recurse
               return ret.Evil(string.Join(".", array.Skip
                   (1).ToArray()));
           return ret;
       }
       static object GetValue(this MemberInfo target, 
           object obj)
       {
           switch (target.MemberType)
           {
               case MemberTypes.Property:
                   return ((PropertyInfo)target).GetValue
                       (obj, null);
               case MemberTypes.Field:
                   return ((FieldInfo)target).GetValue
                       (obj);
               case MemberTypes.Method:
                   return ((MethodInfo)target).Invoke
                       (obj, null);
           }
           return null;
       }
   }
 
It's called 'evil' because
  • 'Evil' sounds a bit like 'eval', which is a bit like what it does
  • It's an extension method, which some may find evil
  • It extends object, which many will find evil
  • Exposing it to users to allow them to choose objects or properties, for example with a Textbox, creates a risk of code injection
  • It doesn't work with parameters, type parameters or indexers (but it could be modified to do so)

Complete example:

using System;
using System.Linq;
using System.Reflection;
namespace EvilObjectExtension
{
    public class Address
    {
        public string Street;
        public string Postcode { get; set; }
        public int HouseNumber;
    }
    public class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public Address Home;
    }
    class Program
    {
        static void Main(string[] args)
        {
            var person = new Person
            {
                Age = 893,
                Home = new Address
                {
                    HouseNumber = 10,
                    Street = "High Road",
                    Postcode = "SW13 3AD"
                }
                ,
                Name = "Rupert"
            };
            Console.WriteLine("Name: {0}", person.Evil("Name"));
            Console.WriteLine("Age: {0}", person.Evil("Age"));
            Console.WriteLine("Postcode: {0}", person.Evil
                ("Home.Postcode"));
            //"Now.Now.Now.DayOfWeek.ToString" works because 
            //Type.GetMember searches the current type and its 
            //base types, and DateTime.Now is itself DateTime.
            Console.WriteLine(DateTime.Now.Evil
                ("Now.Now.Now.DayOfWeek.ToString"));
            //extra delimiters work
            var type = person.Evil(".Home.GetType./");
            Console.ReadKey();
        }
    }
    static class ObjectExtension
    {
        public static object Evil(this object target
            , string s)
        {
            return target.Evil(s, '.', '\\', '/', ',');
        }
        public static object Evil(this object target
            , string s, params  
            char[] separator)
        {
            var array = s.Split(separator,
                StringSplitOptions.RemoveEmptyEntries);
            if (array.Length == 0)
                return target;
            var members = target.GetType().GetMember
                (array.First().Trim());
            if (members.Length == 0)
                return null;
            var ret = members.First().GetValue(target);
            if (array.Length > 1)//recurse
                return ret.Evil(string.Join(".", array.Skip
                    (1).ToArray()));
            return ret;
        }
        static object GetValue(this MemberInfo target, 
            object obj)
        {
            switch (target.MemberType)
            {
                case MemberTypes.Property:
                    return ((PropertyInfo)target).GetValue
                        (obj, null);
                case MemberTypes.Field:
                    return ((FieldInfo)target).GetValue
                        (obj);
                case MemberTypes.Method:
                    return ((MethodInfo)target).Invoke
                        (obj, null);
            }
            return null;
        }
    }
}
email it!bookmark it!digg it!

Original Post: Evil Extension method

Subscribe

New Feed

Product Spotlight

Recently Updated Sources

Legal Note

The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.

Advertise with us