【问题标题】:Keep an assembly alive which is loaded through reflection使通过反射加载的程序集保持活动状态
【发布时间】:2014-08-10 08:41:31
【问题描述】:

我正在尝试通过定义一个通用接口然后通过反射在当前应用程序域中动态加载程序集来为我的应用程序创建一个插件系统。这是主应用程序的代码:

var asm = Assembly.Load(an);
var types = asm.GetTypes();
foreach (var type in types)
{
    if (type.GetInterface(typeof(IModule).ToString()) != null)
    {
        IModule module = null;
        try
        {
            module = asm.CreateInstance(type.ToString(), true) as IModule;
        }
        catch (Exception)
        {

        }
        if (module != null)
        {
            _modules.Add(module);//These objects implement plugin interface
        }

    }
}

问题是,即使我在类级别缓存插件的 IModule 对象,它似乎也被垃圾收集了。下面是演示问题的插件代码:

internal class SamplePlugin : IModule
{
    public void Initialize() // IModule implementation
    {
        _timer = new System.Timers.Timer(1000);
        _timer.Enabled = true;
        _timer.Elapsed += TimerElapsed;
    }

    //This method never gets called
    void TimerElapsed(object sender, ElapsedEventArgs e)
    {
    }
} 

当我在缓存的 IModule 对象上调用初始化方法时,初始化方法被成功调用。但是 TimerElapsed 方法从未被调用,这表明该对象已被 CLR 垃圾回收。

【问题讨论】:

  • 你在哪里缓存它们?也许这会提前处理/超出范围。
  • 我在类级别缓存它们(作为一个字段),当前类是 Main 类的一个字段。所以不知道为什么会这样。也许插件程序集被卸载或什么的。
  • 否,程序集无法从默认域中卸载。
  • 请在格式化您的代码方面付出更多努力 - 在发布之前先查看预览,然后问问自己,如果您正在阅读这篇文章,您是否希望它是这样的。
  • 您可能需要显示更多代码。我的猜测是计时器超出范围,或已处置或 SamplePlugin 实例本身 GC'd

标签: c# clr appdomain


【解决方案1】:

通过缓存程序集对象也解决了这个问题。不知道为什么需要它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 2012-03-09
    • 2020-05-01
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多