使所有使用反射的代理为空

本文关键字:代理 反射的 | 更新日期: 2023-09-27 18:24:59

我有一些代码:

private static st_createInstance        createInstance;
private static st_destroyInstance       destroyInstance;
private static st_getVersionId          getVersionId;
private static st_getVersionString2     getVersionString2;
//...
[UnmanagedFunctionPointer (CallingConvention.StdCall)]
private delegate IntPtr st_createInstance ();
[UnmanagedFunctionPointer (CallingConvention.StdCall)]
private delegate void st_destroyInstance (IntPtr pHandle);
//...

现在,如何使用反射使所有这些代理无效?(我知道如何将字段与委托类型进行比较)。

编辑:我想用一种简单的方式将它们全部置空,比如foreach循环。不希望指定每个字段名称。

使所有使用反射的代理为空

如果type是委托字段所在的对象类型,请尝试以下操作:

var fields = type.GetFields(BindingFlags.Static | BindingFlags.NonPublic);
fields = fields.Where(f => f.FieldType.BaseType == typeof(System.MulticastDelegate));
foreach (FieldInfo fi in fields)
{
    fi.SetValue(null, null);
}

SetValue中的第一个null表示它是一个静态字段,第二个用于将字段的值设置为null

这强烈暗示了一个XY问题。当OP没有解释为什么他需要做某事时,这总是一个问题。当您试图执行pinvokemarshaller对[DllImport]属性所做的工作时,您会编写这种代码。

如果这是准确的,那么请注意,将这些委托对象设置回null没有什么意义,即使它们是静态的。它们实际上引用了thunk,这是一小段自动生成的代码,用于在非托管代码和托管代码之间封送。通常,它只不过是一条简单的JMP指令,当需要重新调整堆栈帧时,它会变得更加复杂。

委托对象本身需要一个GC堆的小分支,只有32个字节。您将希望避免编写使用反射来消除约36个字节的代码,这在时间或空间上都没有回报。代码已经大于您释放的内存。更不用说真正的成本了,你维护这个代码。

考虑去掉初始化这些委托的代码。几乎从来没有必要,pinvoke马歇尔已经非常擅长自己做这件事了。您只需要帮助它找出在哪里可以找到DLL,有比使用LoadLibrary()更好的方法。例如,请检查此答案。