|
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis is an example of how to use the new BackgroundAt my current company we have built our own Object-Relational-Mapper (ORM), similar to nHibernate. In order to do this we were using reflection to set the properties/fields of an SolutionFortunately, along came .NET 2.0 and the DetailsHere’s the important code in the included download (the other classes are just for demo). public delegate object GetHandler(object source);
public delegate void SetHandler(object source, object value);
public delegate object InstantiateObjectHandler();
public sealed class DynamicMethodCompiler
{
// DynamicMethodCompiler
private DynamicMethodCompiler() { }
// CreateInstantiateObjectDelegate
internal static InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
{
ConstructorInfo constructorInfo = type.GetConstructor(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
if (constructorInfo == null)
{
throw new ApplicationException(string.Format("The type {0} must declare an
empty constructor (the constructor may be private, internal,
protected, protected internal, or public).", type));
}
DynamicMethod dynamicMethod = new DynamicMethod("InstantiateObject",
MethodAttributes.Static |
MethodAttributes.Public, CallingConventions.Standard, typeof(object),
null, type, true);
ILGenerator generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Newobj, constructorInfo);
generator.Emit(OpCodes.Ret);
return (InstantiateObjectHandler)dynamicMethod.CreateDelegate
(typeof(InstantiateObjectHandler));
}
// CreateGetDelegate
internal static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
{
MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true);
DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
ILGenerator getGenerator = dynamicGet.GetILGenerator();
getGenerator.Emit(OpCodes.Ldarg_0);
getGenerator.Emit(OpCodes.Call, getMethodInfo);
BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
getGenerator.Emit(OpCodes.Ret);
return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
}
// CreateGetDelegate
internal static GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
{
DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
ILGenerator getGenerator = dynamicGet.GetILGenerator();
getGenerator.Emit(OpCodes.Ldarg_0);
getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
BoxIfNeeded(fieldInfo.FieldType, getGenerator);
getGenerator.Emit(OpCodes.Ret);
return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
}
// CreateSetDelegate
internal static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
{
MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true);
DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
ILGenerator setGenerator = dynamicSet.GetILGenerator();
setGenerator.Emit(OpCodes.Ldarg_0);
setGenerator.Emit(OpCodes.Ldarg_1);
UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
setGenerator.Emit(OpCodes.Call, setMethodInfo);
setGenerator.Emit(OpCodes.Ret);
return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
}
// CreateSetDelegate
internal static SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
{
DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
ILGenerator setGenerator = dynamicSet.GetILGenerator();
setGenerator.Emit(OpCodes.Ldarg_0);
setGenerator.Emit(OpCodes.Ldarg_1);
UnboxIfNeeded(fieldInfo.FieldType, setGenerator);
setGenerator.Emit(OpCodes.Stfld, fieldInfo);
setGenerator.Emit(OpCodes.Ret);
return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
}
// CreateGetDynamicMethod
private static DynamicMethod CreateGetDynamicMethod(Type type)
{
return new DynamicMethod("DynamicGet", typeof(object),
new Type[] { typeof(object) }, type, true);
}
// CreateSetDynamicMethod
private static DynamicMethod CreateSetDynamicMethod(Type type)
{
return new DynamicMethod("DynamicSet", typeof(void),
new Type[] { typeof(object), typeof(object) }, type, true);
}
// BoxIfNeeded
private static void BoxIfNeeded(Type type, ILGenerator generator)
{
if (type.IsValueType)
{
generator.Emit(OpCodes.Box, type);
}
}
// UnboxIfNeeded
private static void UnboxIfNeeded(Type type, ILGenerator generator)
{
if (type.IsValueType)
{
generator.Emit(OpCodes.Unbox_Any, type);
}
}
}
Each of these methods takes a Unfortunately, I have a very limited understanding of IL, so I'm unable to give an in-depth explanation of what’s going on under the hood here. I had to do a fair amount of Googling, decompiling, and good old fashioned trial and error to write this code. Here's what the public delegate object GetHandler(object source);
This Type type = typeof(<your class>);
FieldInfo fieldInfo = type.GetField(<field or property name>, BindingFlags.Instance |
BindingFlags.NonPublic | BindingFlags.Public);
GetHandler getHandler = DynamicMethodCompiler.CreateGetHandler(type, fieldInfo);
And here's an example of how to use the MyClass myClass = new MyClass();
myClass.MyProperty = 4;
int currentValue = (int)getHandler(myClass);
In this example, Note that there is still some reflection involved. You still need to get a reference to the appropriate reflection
|
||||||||||||||||||||||||||||||