WeakReference, WeakEvents:用于动态加载/卸载服务器模块,dll
本文关键字:卸载 服务器 dll 模块 动态 WeakEvents 用于 WeakReference 加载 | 更新日期: 2023-09-27 18:15:52
我在想WeakReferences和WeakEvents是否适用于服务器模块接口的情况。这是一个好的设计吗?
但也有性能问题,当然需要在WeakEvent模式中调用和访问WeakReference,也许太
更新:细节服务器:
- 有模块管理器,
- 可以通过共享接口IModule加载/卸载DLL的实现类
- 模块管理器创建并保存IModule的实例,
模块:
- 有名称或唯一代码,
- 需要与其他模块交互,使用他们的方法,属性,事件,
问题是,当一个模块获得另一个模块的实例时(通过名称提供,例如从模块管理器),那么从那时起,就不能保证该模块可以在卸载之前被垃圾收集。
但是可能存在一个给定IModule实现的泛型类(WeakRefModule where T: IModule),约束为IModule,它可以在IModule内部存储WeakReference。然后给定的模块将通过基于WeakRefModule的扩展方法或继承来公开其公共方法。将模块的实例隐藏在WeakReference后面。属性和事件(WeakEvents)也是一样。
这样的模块总是保证其他模块不能阻止它被垃圾回收。
所以问题是,它在多大程度上是一个好的设计,是否有一些隐藏的问题?
这个设计基本上是有效的。您需要确保对希望保持加载的模块有一个强引用。否则,GC将不确定地杀死弱引用。
一个问题是模块不能依赖其他存在的模块。如果一个模块被卸载并且弱ref变为null,对该模块的调用将失败或什么都不做。此外,ref变为null的时间点是不确定的。
我不会在这里使用弱引用。你可以创建一个包装器IModule,它只委托给另一个IModule。然后,当你想卸载一个模块时,你可以清除这个包装器。
class WrappedModule : IModule {
IModule inner;
public void Dispose() { inner = null; }
void IModule.SomeMeth() {
if (inner == null) throw ...;
else inner.SomeMeth();
}
}
现在您可能会泄漏包装器对象,但它很小。你不会领导真正的模块。
模块永远不能直接访问其他模块。相反,它们被传递给这个"句柄"类。此句柄可随时禁用