C# 使用反射使所有代理为空

C# 使用反射使所有代理为空,c#,reflection,delegates,C#,Reflection,Delegates,我有一些代码: private static st_createInstance createInstance; private static st_destroyInstance destroyInstance; private static st_getVersionId getVersionId; private static st_getVersionString2 getVersionString2; //... [Unmanag

我有一些代码:

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);

//...
现在,如何使用反射使所有这些委托无效?(Idk如何将字段与委托类型进行比较)


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

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

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
如果
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没有解释为什么他需要做某事时,这总是一个问题。当您尝试执行pinvoke marshaller使用[DllImport]属性所做的工作时,您可能会编写这种代码

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

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


考虑删除初始化这些委托的代码。几乎没有必要,品沃克马歇尔勒已经非常擅长自己做这件事了。您只需要帮助它找到DLL的位置,有比使用LoadLibrary()更好的方法。检查示例。

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

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

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


考虑删除初始化这些委托的代码。几乎没有必要,品沃克马歇尔勒已经非常擅长自己做这件事了。您只需要帮助它找到DLL的位置,有比使用LoadLibrary()更好的方法。检查示例。

查看我的问题,我现在解释得更好了。它不能投射。所以我修改了行“fields=fields.Where…”到“var newFields=fields.Where…”。它现在工作正常,但还有一个我不理解的附加字段:System.Func`2[[System.Reflection.FieldInfo,mscorlib,Version=4.0.0.0,Culture=n eutral,PublicKeyToken=b77a5c561934e089],[System.Boolean,mscorlib,Version=4.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]]在我发布新答案后不久,我更新了我的答案-确保你有
f=>f.FieldType.BaseType
,而不仅仅是
f=>f.BaseType
。看我的问题,我现在解释得更好了。它不能强制转换。所以我修改了行“fields=fields.Where…”到“var newFields=fields.Where…”。它现在工作正常,但还有一个我不理解的附加字段:System.Func`2[[System.Reflection.FieldInfo,mscorlib,Version=4.0.0.0,Culture=n eutral,PublicKeyToken=b77a5c561934e089],[System.Boolean,mscorlib,Version=4.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089]]在我发布新答案后不久,我更新了它-确保您有
f=>f.FieldType.BaseType
,而不仅仅是
f=>f.BaseType
(1)将它们嵌套在
struct
(值类)中。您只能有一个静态实例。(2) 使用刚刚使用
new
创建的新实例分配静态成员变量(1)将它们嵌套在
struct
(值类)中。您只能有一个静态实例。(2) 使用刚刚使用
new
创建的新实例分配静态成员变量。thunk确实会被释放。“收集委托时,非托管封送处理代码将被删除。”天哪,看起来太复杂了。明天我会仔细读的,因为我现在太累了。我只是想在GetDelegateForFunctionPointer在一个或多个调用中失败时将这些委托设为null(例如,如果我没有加载我想要的DLL文件)。如果无法加载DLL,则根本无法初始化委托对象。改进错误处理,永远不要忽略LoadLibrary和GetProcAddress的返回值。场景:1)加载错误的dll文件2)尝试使用GetDelegateForFunctionPointer创建委托。3) 若一些委托为null,那个么就有错误的dll库,所以我可以抛出异常或其他东西。A) 使用反射检查所有这些代理是否都不为空,可以吗?B) 如果库是错误的,那么我只需要保持静态字段不变,而不使其为空?当加载错误的DLL时,您真正希望发生什么?试图将它们设置回null只是徒劳