some random reflection extensions i was using

This commit is contained in:
goyuken 2014-10-19 23:15:52 +00:00
parent b4d065869e
commit 4c1b31e293
1 changed files with 46 additions and 0 deletions

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace BizHawk.Common.ReflectionExtensions
{
@ -160,5 +162,49 @@ namespace BizHawk.Common.ReflectionExtensions
{
return (T)o.GetType().GetCustomAttributes(typeof(T), false)[0];
}
/// <summary>
/// where the fields begin relative to the address an object references points to
/// </summary>
public static IntPtr ManagedFieldStart { get { return _managedfieldstart; } }
[StructLayout(LayoutKind.Explicit)]
private class Junkus { [FieldOffset(0)]public IntPtr s; }
static IntPtr _managedfieldstart = GetManagedOffset(typeof(Junkus).GetField("s"));
/// <summary>
/// the address of a field relative to the address an object reference of that type points to. this function is very expensive to call.
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
public static IntPtr GetManagedOffset(this FieldInfo field)
{
Type type = field.DeclaringType;
var dyn = new System.Reflection.Emit.DynamicMethod(
"xxz0", typeof(IntPtr), new Type[] { typeof(object) }, typeof(ReflectionExtensions).Module, true);
var il = dyn.GetILGenerator();
var pin = il.DeclareLocal(type, true);
var baseaddr = il.DeclareLocal(typeof(IntPtr));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Stloc, pin); // force cast object to type (invalid), and pin
il.Emit(OpCodes.Ldloc, pin); // base address of reference (points to typeinfo)
il.Emit(OpCodes.Conv_I); // convert object ref to intptr (invalid)
il.Emit(OpCodes.Stloc, baseaddr);
il.Emit(OpCodes.Ldloc, pin);
il.Emit(OpCodes.Ldflda, field); // address of desired field
il.Emit(OpCodes.Conv_I); // convert field& to intptr (invalid)
il.Emit(OpCodes.Ldloc, baseaddr);
il.Emit(OpCodes.Sub);
il.Emit(OpCodes.Ret);
return (IntPtr)dyn.Invoke(null, new object[] { new object() });
}
}
}