Ill*_*ack 5 c# clr interop typedreference
我终于明白了该方法的用法TypedReference.MakeTypedReference,但为什么参数如此有限?底层的 private可以做比限制字段数组有元素和字段类型为非原始的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);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,实际调用它需要更多技巧,因为它不能被调用,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
Run Code Online (Sandbox Code Playgroud)
那么,为什么开发人员看似毫无意义地决定禁止这种用法,而这显然是有用的呢?
责怪柏拉图和他该死的“类型论”......
这是任何(托管指针)引用本质上所固有的ref——包括新的 C# 7 ref local和ref return功能——正如您所观察到的,TypedReference,您可以使用它来读取和写入目标。因为这不是重点吗?
现在,由于CTS无法排除其中任何一种可能性,因此强类型要求每个Type元素都ref受到类型层次结构中上层和下层的约束。
更正式地说,Type被限制为多态协变和逆变的交集,否则它就符合条件。显然,这个交集的结果折叠成一个, 本身,从此以后它是不变的。Type