Here is an another option for creating a delegate when you are working with objects (don't know specific type of a field). Though it is slower if field is a structure (because of boxing).
public static class ReflectionUtility
{
public static Func CompileGetter(this FieldInfo field)
{
string methodName = field.ReflectedType.FullName + ".get_" + field.Name;
DynamicMethod setterMethod = new DynamicMethod(methodName, typeof(object), new[] { typeof(object) }, true);
ILGenerator gen = setterMethod.GetILGenerator();
if (field.IsStatic)
{
gen.Emit(OpCodes.Ldsfld, field);
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
}
else
{
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, field.DeclaringType);
gen.Emit(OpCodes.Ldfld, field);
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
}
gen.Emit(OpCodes.Ret);
return (Func)setterMethod.CreateDelegate(typeof(Func));
}
public static Action CompileSetter(this FieldInfo field)
{
string methodName = field.ReflectedType.FullName + ".set_" + field.Name;
DynamicMethod setterMethod = new DynamicMethod(methodName, null, new[] { typeof(object), typeof(object) }, true);
ILGenerator gen = setterMethod.GetILGenerator();
if (field.IsStatic)
{
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
gen.Emit(OpCodes.Stsfld, field);
}
else
{
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, field.DeclaringType);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
gen.Emit(OpCodes.Stfld, field);
}
gen.Emit(OpCodes.Ret);
return (Action)setterMethod.CreateDelegate(typeof(Action));
}
}