我在使用 Outlook 插件时遇到了非常奇怪的程序集参考问题和加载问题。以下是详细信息(说来话长:)):
我有一个旧的 Outlook 插件,使用 .Net 1.1 编写和构建。插件是使用其自己的应用程序域中的非托管 shim 加载的。使用 .Net 2.0 可以正常工作,即使用户机器上不存在 1.1。
该插件使用由 VS 2003 针对 Outlook 2000 创建的自定义 Outlook 互操作程序集,然后重建为强命名(就像我的插件一样)。
在插件项目中,我只引用了这个自定义互操作程序集,没有引用官方的 MS 互操作程序集。
当这个插件在 Outlook 2007 和 .Net 2.0 的环境中使用时,官方的 MS 互操作程序集安装在 GAC 中,出于某种原因,我看到插件加载并使用它们。
在 Connect 类的代码中,我有一个 using 指令:
using Outlook;
这是我的自定义互操作程序集的命名空间。
在 Connect ctor 我有这些代码行(添加用于测试目的):
Assembly.LoadFrom(PATHTOMYASSEMBLY + "Interop.Outlook.dll");
Type type = typeof(Outlook.ApplicationClass);
logger.Debug("Outlook.Application full type is: {0}", type.AssemblyQualifiedName);
这输出:
Outlook.Application 完整类型为:Outlook.ApplicationClass、Interop.Outlook、Version=9.0.0.0、Culture=neutral、PublicKeyToken=4cfbdc5349cf59d8
这正是我所期望的。
问题是,当调用 OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) 时,我在日志中看到 MS 互操作(我有一个当前域的 AssemblyLoad 事件的挂钩)程序集也被加载:
private void app_domain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
Assembly loadedAssembly = args.LoadedAssembly;
logger.Debug("Assembly {0} is loaded from: {1}", loadedAssembly.FullName, loadedAssembly.GlobalAssemblyCache ? "GAC" : loadedAssembly.Location);
}
输出:
程序集 Microsoft.Office.Interop.Outlook,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c 加载自:GAC
我的 OnConnection 方法是这样开始的:
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
Type type = application.GetType();
logger.Debug("OnConnection application object's full type is: {0}", type.AssemblyQualifiedName);
Outlook.Application applicationObject = (Outlook.Application)application;
这输出:
OnConnection 应用程序对象的完整类型是:Microsoft.Office.Interop.Outlook.ApplicationClass, Microsoft.Office.Interop.Outlook, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
这真的很奇怪,你可以在下一行看到我可以成功地转换到 Outlook.Application 没有任何问题。
我已经检查过 Reflector,我的程序集不以任何方式引用 Microsoft 的互操作程序集。我的 Interop.Outlook.dll 也是如此。
那么,有人知道发生了什么吗?这些问题的答案是什么:
为什么它会加载 Microsoft 程序集?
如何在不同程序集中定义的不相关类/接口之间进行转换?
注意:我创建了一个新插件,非常简单,它什么都不做,只是加载。我可以重现这个问题,所以真的,有谁知道 CLR 如何决定加载什么互操作以及从哪里加载。除了在 GAC 中,还有其他地方(注册表???)在 COM 对象和它所需的互操作之间存在链接?