Thursday, May 6, 2010

Building a better dynamic! .NET 4.0

So, you installed .NET 4.0 and think some of the new features are pretty cool...  but you have to wonder, what cool new things you can do beyond the "var" equivalent in javascript.  (!!!Disclaimer!!! var in .NET is not even remotely the same as var in javascript.  Dynamic objects in C# are created using the "dynamic" keyword NOT the var keyword.  The var keyword is compile time in C#!  I had to say it... all the other cool kids are.  ;-)  )


Batter up, who wants to build a BadAssDynamic
Now I know everyone is hating what I named this, your boss is looking at your computer screen, but to protect the innocent colleague of mine *cough*Tim*cough* and his love for the power rangers, I will not use the other cool name I used in a real project.


First up:   How often did you really want to access a property name at runtime by it's string name?  Wouldn't it have been nice if you could have done:
dynamic obj = new CustomObjectTypePerhapsAnEntity();
obj["PropertyName"] = value;


Well that is what I am here to show you how to do today.  Lets take a look at some code!




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


namespace NOC.Enterprise.Common.NetExtensions
{
    public class BadAssDynamic
    {
        protected Dictionary<string, Property> properties;
        protected dynamic obj;


        public dynamic this[string i]
        {
            get
            {
                return properties[i].Value;
            }
            set
            {
                properties[i].Value = value;
            }
        }


        private BadAssDynamic() { }
        public BadAssDynamic(dynamic d)
        {
            obj = d;
            Type t = d.GetType();


            this.SeedProperties(t);
        }


        public BadAssDynamic(Type t)
        {
            var constructors = t.GetConstructors();
            var constructor = constructors.Single(x => x.GetParameters().Count() == 0);


            if (constructor == null)
                throw new NullReferenceException("BadAssDynamic(..) requires the type to contain a parameterless constructor.");


            obj = constructor.Invoke(new object[] { });


            this.SeedProperties(t);
        }


        private void SeedProperties(Type t)
        {
            properties = new Dictionary<string, Property>();
            foreach (PropertyInfo p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                properties.Add(p.Name, new Property(this, p));
            }
        }


        public dynamic GetActualObject()
        {
            return obj;
        }


        public class Property
        {
            protected BadAssDynamic _dynamic;
            protected PropertyInfo _pi;


            public Property(BadAssDynamic badAssDynamic, PropertyInfo pi)
            {
                _dynamic = badAssDynamic;
                _pi = pi;
            }


            public dynamic Value
            {
                get { return _pi.GetValue(_dynamic.obj, null); }
                set { _pi.SetValue(_dynamic.obj, value, null); }
            }
        }
    }
}






Woah... lots of italics code, and yes this time straight from my IDE.


So what does this do? 


First the above code was not entirely possible until the addition of "dynamic" with .NET 4.0.  It still uses some old school reflection despite having the "dynamic" keyword, but Microsoft only gave us a brain dead object.


The BadAssDynamic has a sub-class of "Property" which due to another brain dead move my M$ you have to have a manual reference to the parent within the subclass.  This is essentially a wrapper around the PropertyInfo object, you could live without it if you truly desire.




        private void SeedProperties(Type t)
        {
            properties = new Dictionary<string, Property>();
            foreach (PropertyInfo p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                properties.Add(p.Name, new Property(this, p));
            }
        }




The above code is the magic that drives this object.  Upon initialization of the BadAssDynamic it populates a dictionary of type <string, Property> for all public instance properties belonging to the object.  This is then accessed by the array index accessors




        public dynamic this[string i]
        {
            get
            {
                return properties[i].Value;
            }
            set
            {
                properties[i].Value = value;
            }
        }

This is the core functionality of the BadAssDynamic, you might not know of a piratical use for this yet... BUT next blog post...  I'll show you some crazy uses for this object.

If you are looking for IT solutions for your businesses, would like to provide feedback, or give us a referral for new business opportunities (We provide profit sharing on referrals), you can visit our website at www.NightOwlCoders.com.  We service all of the US for Web Site design, and offer consulting services throughout Pittsburgh, Butler, Cranberry, and New Castle, PA.  Lawrence County, Butler Country, Mercer County, and Allegheny County.

~Aqua~