对 IE 工具栏中实例的静态引用
本文关键字:静态 引用 实例 IE 工具栏 | 更新日期: 2023-09-27 17:56:16
我在编写为在IE中用作工具栏的COM组件时遇到了一个有趣的问题。 基本上,如果您在IE中一次打开多个选项卡,则COM对象的各个实例都会扭曲。 在这里请耐心等待。
假设我通过右键单击几个不同的链接并在新选项卡中打开它们,一次打开五个浏览器选项卡。 现在,我的工具栏的一个功能涉及在网页中选择文本,然后单击按钮将该文本复制到工具栏中。 因此,让我们在选项卡 3 中执行此操作。 我们选择文本并单击按钮,但什么都没有。 但是,如果我们在选项卡 2 中选择文本,然后返回选项卡 3 并单击按钮,我们将获得在选项卡 2 中选择的文本。 所以。。。选项卡 3 中的工具栏从选项卡 2 获取内容。 不好。
我已经将这个问题追溯到我们的 COM 对象(工具栏)中的静态引用。
[ComVisible(true), Guid("2CC75392-1182-470D-BECC-EFA33E629AB8")]
[CLSCompliant(false)]
public sealed class Toolbar : ADXIEToolbar
{
public static Toolbar Instance;
public Toolbar()
{
Instance = this;
InitializeComponent();
}
...other code...
}
请注意,每个 IE 选项卡仅存在一个工具栏实例。
此引用未正确分配,几乎就像它不是线程安全的(它不是),而是不是域安全或其他东西。 它有时会引用另一个实例。 与其他静态字段甚至线程安全的单例相同。 我不明白。
另请注意,如果我将对这个工具栏的引用(在 InitializeComponent 内部)传递给控件,我会遇到同样的问题。
this.publicationDateCb.Toolbar = this;
此引用有时会指向不同的选项卡。
如果我使用纯粹基于订阅的模型,绝对零静态引用,工具栏作为裁判,那么事情似乎工作正常。 这基本上意味着我必须重新设计程序,使其没有类直接相互交互 - 它们触发工具栏订阅的事件,调用其他类中的方法。 哎哟。
那么我应该使用那个模型(这可能是理想的,但我在这里走得很远)还是我在这里缺少一个简单的修复?
其他注意事项:
- 所有 IE 选项卡都在单独的进程中运行。
- BHO/工具栏在与 IE 选项卡相同的进程中运行。
- 我正在使用 Internet Explorer 的 Add-In-Express 来处理 IE 集成。
- 该项目是为 .NET 3.5 编写的;加载程序使用 .NET 2.0 。
如果要在所有工具栏中共享所选文本,可以查看: http://www.add-in-express.com/creating-addins-blog/2009/06/19/internet-explorer-plugin-settings-synchronize/
问题解决了,但静态引用消失了。 我做了几件事:
首先,我将目标 .NET 版本更改为 4.0。 显然,用 4.0 编写的 BHO 效果更好 - 我找不到链接来证实这一说法,但我在某处读过它。
更重要的是,我完全取消了程序集中的静态引用。 我摆脱了单例,而是为工具栏类中的每个以前的单例类创建了一个属性,该属性将始终是唯一的。 然后,每当一个类需要引用以前的单例时,我都会传递对工具栏的引用。
所以。。。构造函数现在如下所示:
internal class RegistryData
{
public RegistryData(Toolbar toolbar)
{
ToolbarRef = toolbar;
}
...
}
假设RegistryData需要调用消息传递。
private void RegistryUpdated(int keyId)
{
ToolbarRef.Messaging.SendMessage(keyId);
}
巨大的痛苦,对吧? 工作时间。 但问题解决了。 如果这个问题只与外接程序有关,我不会感到震惊。