Проверьте заранее, если сборка может быть найдена - PullRequest
2 голосов
/ 30 мая 2011

Моя программа .net использует сборку, которая должна быть установлена ​​в GAC.

Если сборка установлена ​​правильно, она будет загружена, как только я использую ее в первый раз, и это здорово. Если, например, я использую тип из сборки, как это:

ESRI::ArcGIS::esriSystem::AoInitialize^  aoi = gcnew ESRI::ArcGIS::esriSystem::AoInitializeClass();

Сборка будет загружена.

Теперь иногда сборка не будет присутствовать в GAC, и мне нужно, чтобы программа знала об этом, но не вылетала.

Я попытался обернуть использование сборки в блок try / catch следующим образом:

try
{
  ESRI::ArcGIS::esriSystem::AoInitialize^  aoi = gcnew  ESRI::ArcGIS::esriSystem::AoInitializeClass();
}
catch (System::Exception^ )
{
  // assembly not found
}

Но программа не выдаст исключение, а вместо этого вылетит.

Как я могу заранее проверить, находится ли сборка в GAC и может ли она использоваться без сбоев? Или как я мог поймать сбой и отключить соответствующие пункты меню в моей программе?

Ответы [ 2 ]

2 голосов
/ 30 мая 2011

У вас неправильная ментальная модель способа загрузки сборок. не происходит при создании экземпляра типа в сборке.JIT-компилятор - это тот, который сначала нуждается в сборке.Сгенерировать машинный код для метода.Если вы посмотрите на стек вызовов для исключения, то увидите, что исключение возникло в вызывающем методе .

По крайней мере, это обычно происходит, когда вы используете джиттер Microsoft, он генерирует машинный код по требованию, в самый последний момент.Он отличается для других джиттеров, таких как Mono, он компилируется гораздо быстрее.

Вы можете поймать исключение в вызывающем методе, но это довольно хрупко.Кроме зависимости джиттера, вам также придется приписывать метод с помощью [MethodImpl (MethodImplOptions.NoInlining)], чтобы этот код никогда не вставлялся в строку.Потому что это снова приведет к тому, что тип понадобится слишком рано.

Надлежащее решение - использовать архитектуру плагина.Вы должны использовать тип интерфейса для объявления свойств и методов, которые вы хотите использовать в своей основной программе.Этот тип интерфейса должен быть объявлен в отдельной сборке со ссылкой как вашей основной программой, так и плагином.И развернуто с вашей основной программой, независимо от того, доступна ли опция плагина для вашего клиента.Используйте Assembly.Load (), чтобы загрузить сборку плагина, и Assembly.CreateInstance (), чтобы создать конкретный экземпляр типа, который реализует интерфейс.И никогда не обращайтесь к конкретному типу в вашем коде, только к типу интерфейса.Вы найдете много примеров этого с запросом Google.

0 голосов
/ 30 мая 2011

Лучшим способом было бы добавить все необходимые сборки в процессе установки.

Однако, то, чего вы хотите, может быть достигнуто с помощью простой проверки типа перед созданием типа.

Что-токак это:

var t = System.Type.GetType("TypeName, Assembly");
if (t == null) throw CannotLoadTypeException();
...