我终于明白了它的用法TypedReference.MakeTypedReference方法,但为什么论据如此有限?底层私有InternalMakeTypedReference(void* result, object target, IntPtr[] flds, RuntimeType lastFieldType)
可以做的事情比MakeTypedReference
这限制了字段数组具有元素并且字段类型是非原始的。
我制作了一个示例使用代码,展示了它的全部可能性:
private static readonly MethodInfo InternalMakeTypedReferenceMethod = typeof(TypedReference).GetMethod("InternalMakeTypedReference", flags);
private static readonly Type InternalMakeTypedReferenceDelegateType = ReflectionTools.NewCustomDelegateType(InternalMakeTypedReferenceMethod.ReturnType, InternalMakeTypedReferenceMethod.GetParameters().Select(p => p.ParameterType).ToArray());
private static readonly Delegate InternalMakeTypedReference = Delegate.CreateDelegate(InternalMakeTypedReferenceDelegateType, InternalMakeTypedReferenceMethod);
public static void MakeTypedReference([Out]TypedReference* result, object target, params FieldInfo[] fields)
{
IntPtr ptr = (IntPtr)result;
IntPtr[] flds = new IntPtr[fields.Length];
Type lastType = target.GetType();
for(int i = 0; i < fields.Length; i++)
{
var field = fields[i];
if(field.IsStatic)
{
throw new ArgumentException("Field cannot be static.", "fields");
}
flds[i] = field.FieldHandle.Value;
lastType = field.FieldType;
}
InternalMakeTypedReference.DynamicInvoke(ptr, target, flds, lastType);
}
不幸的是,实际上调用它需要更多的技巧,因为它不能从MethodInfo
一个参数是RuntimeType
,因此必须动态生成委托类型(DynamicMethod
也可以使用)。
现在这能做什么呢?它可以不受限制地访问任何对象的任何值的任何字段(类或结构类型,甚至原始类型)。此外,它还可以创建对装箱值类型的引用。
object a = 98;
TypedReference tr;
InteropTools.MakeTypedReference(&tr, a);
Console.WriteLine(__refvalue(tr, int)); //98
__refvalue(tr, int) = 1;
Console.WriteLine(a); //1
那么,为什么开发人员看似毫无意义地决定禁止这种用法,而这显然是有用的呢?