Gieno Dynamic in C# 4.0, Part 8 | ||
After
7 posts on dynamic for learning, this time I think it's much more to fun to use it for something evil… by making Reflection simple.
In C# 3.0 invoking members through reflection, was kind of odd and certainly not very readable.
var employee
=
new
Employee(); By wrapping all reflection magic in a dynamic object the same call would look like:
var members = employee.GetType().GetMember( " age " , MemberTypes.All, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public ); ((FieldInfo)members[ 0 ]).SetValue(employee, 30 );
var employee
=
(
new
Employee()).AsDynamic(); How this works is relatively easy.. by deriving a wrapper class from the new
DynamicObject and overriding the
TrySetMember and
TryGetMember object to do the dirty work for you.
employee.Name = " Gieno Miao " ; employee.Age = 26 ; Console.WriteLine( " Employee {0} is {1} years old. " , employee.Name, employee.Age); ![]() ![]() static class DynamicHelper { public static dynamic AsDynamic(this T source) { return new DynamicReflection(source); } class DynamicReflection : DynamicObject { public DynamicReflection(T source) : base() { this.Source = source; } public override bool TrySetMember(SetMemberBinder binder, object value) { // find the member MemberInfo member; if (!TryFindMember(binder.Name, out member)) { return false; } // we can only set values to fields and properties // using reflection switch (member.MemberType) { /* todo: check the type of the incoming value and the type of the property. */ case (MemberTypes.Field): ((FieldInfo)member).SetValue(Source, value); return true; case (MemberTypes.Property): ((PropertyInfo)member).SetValue(Source, value,/*ndex*/ null); // we don't support indexed properties return true; } // didn't work return false; } public override bool TryGetMember(GetMemberBinder binder, out object result) { // find the member MemberInfo member; if (!TryFindMember(binder.Name, out member)) { result = null; return false; } // we can only set values to fields and properties // using reflection switch (member.MemberType) { /* todo: check the type of the incoming value and the type of the property. */ case (MemberTypes.Field): result = ((FieldInfo)member).GetValue(Source); return true; case (MemberTypes.Property): result = ((PropertyInfo)member).GetValue(Source,/*ndex*/ null); // we don't support indexed properties return true; } // didn't work result = null; return false; } private bool TryFindMember(string name, out MemberInfo memberInfo) { // find the member var members = Type.GetMember(name, MemberTypes.All, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); // more than 1 not supported for now if (members.Length != 1) { memberInfo = null; return false; } memberInfo = members[0]; return true; } private Type Type { get { return typeof(T); } } public T Source { get; private set; } } } | ||