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();
var members = employee.GetType().GetMember( "age", MemberTypes.All,
BindingFlags.IgnoreCase | BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public );
((FieldInfo)members[0]).SetValue(employee, 30);
By wrapping all reflection magic in a dynamic object the same call would look like:
var employee = (new Employee()).AsDynamic();
employee.Name = "Gieno Miao";
employee.Age = 26;
Console.WriteLine("Employee {0} is {1} years old.", employee.Name, employee.Age);
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.
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Demo Code
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; }
}
}As always, happy coding.