Существует очень странная проблема со ссылками на сборки и проблема с загрузкой, с которыми я сталкиваюсь с надстройкой Outlook. Вот деталь (долгая история :)):
У меня есть старый плагин для Outlook, написанный и собранный с использованием .Net 1.1. Надстройка загружается с использованием неуправляемой прокладки в собственном домене приложения. Он работает нормально, с .Net 2.0, даже если 1.1 не присутствует на компьютере пользователя.
Надстройка использует настраиваемую сборку взаимодействия Outlook, созданную VS 2003 для Outlook 2000, и после этого перестраивается под строгим именем (как и мое дополнение).
В проекте надстройки я ссылаюсь только на эту пользовательскую сборку взаимодействия, но не на официальную сборку взаимодействия MS.
Когда этот плагин используется в среде с Outlook 2007 и .Net 2.0, где в GAC установлены официальные сборки взаимодействия MS, по какой-то причине я вижу, что плагин загружает и использует их.
В коде класса 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, версия = 9.0.0.0,
Culture = нейтрально,
PublicKeyToken = 4cfbdc5349cf59d8
Это именно то, чего я ожидал.
Проблема в том, что когда
OnConnection (объект приложения, Extensibility.ext_ConnectMode connectMode, объект addInInst, ссылка System.Array custom)
называется, я вижу в журнале (у меня есть перехват к событию AssemblyLoad текущего домена), что сборка взаимодействия MS также загружается:
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,
Версия = 12.0.0.0, Культура = нейтральная,
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,
Версия = 12.0.0.0, Культура = нейтральная,
PublicKeyToken = 71e9bce111e9429c
Это действительно странно, так как вы можете видеть, что на следующей строке я могу без проблем привести к Outlook.Application.
Я проверил с помощью Reflector, и моя сборка никоим образом не ссылается на сборки взаимодействия Microsoft. То же самое для моего Interop.Outlook.dll.
Так, кто-то знает, что происходит? Каков ответ на эти вопросы:
Почему он вообще загружает сборки Microsoft?
Как можно привести между несвязанными классами / интерфейсами, определенными в разных сборках?
ПРИМЕЧАНИЕ. Я создал новый очень простой плагин, который ничего не делает, просто загружает. Я мог бы воспроизвести проблему, так что, действительно, кто-нибудь знает, как CLR решает, какое взаимодействие загрузить и откуда. Помимо GAC, есть ли другое место (реестр ???), где есть связь между COM-объектом и взаимодействием, которое для этого требуется?