Я в аду.
Я создаю плагин для огромного, древнего и очень мощного программного пакета ANSYS. У них есть плагин рамки. Я надеялся, что они волшебным образом справятся со мной через AssemblyContext
с или AppDomain
с, или с помощью другого умного устройства с сетью точек, которое я не понимаю. Они не.
В результате я создал приложение, которое зависит от GRPC.core 1.16.0 через nuget. Я написал небольшое приложение, которое управляет моим плагином с помощью хоста winform. Он загружается и работает отлично, находя мою библиотеку в ~/myproject/bin/debug/grpc.core.1.1.16.dll
, которая существует прямо рядом с библиотекой классов, которая является моим плагином, без проблем.
Когда я запускаю свой плагин в пространстве процесса ANSYS, что также зависит от grpc 1.0.0.0, компоновщик находит C:\Program FIles\ANSYS\...\WIN64\grpc.core.dll
. Нет хорошо.
Одна странная вещь в пакете Nuget GRPC заключается в том, что он добавляет ссылку с «справочной версией» 1.0.0.0, где большинство других пакетов nuget имеют свою эталонную версию, совпадающую с версией пакета nuget. Если я вручную изменю эталонную версию, компилятор не найдет библиотеку.
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad">
<HintPath>..\packages\Grpc.Core.1.16.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
изменить: ключ находится в строке выше. Опубликованный Nuget артефакт Grpc.core находится на AssemblyInformationVersion=1.16.1.0, AssemblyFileVersion=1.16.1.0, AssemblyVersion=1.0.0.0
. Я зарегистрировал это как запрос против GRPC . Подробнее ниже.
Таким образом, я должен сказать средствам компоновки во время выполнения, чтобы они не использовали grpc.core ... dll, найденный в собственном двоичном каталоге ANSYS. Более того, есть ровно одна dll (и ее зависимые элементы), которую я хочу загрузить из контекста моих родительских процессов. : и это сами API-интерфейсы ANSYS, которые, вероятно, уже есть в GAC. В моем проекте я включил это как ненулевую ссылку с выбранным «действием сборки: не копировать».
Итак, мои вопросы:
- Есть ли что-то простое и легкое, что я могу сделать во время выполнения, чтобы сказать runtime-linker "когда кто-то загружает тип из сборки, которую вы считаете нужным
grpc.core
, не загружайте 1.0.0.0, найдите 1.16. 0.0 точно "?
среда выполнения уже соответствовала нужной библиотеке
имя ". Проблема в том, что 1.16.0 является неправильным. Эта версия
строка была информационной, но сама сборка была версией
1.0.0.0. Fusion загружал нужную мне библиотеку по точному совпадению.
- Есть ли что-то более умное, что я могу сделать с доменами приложений или контекстами или другим устройством C #, чтобы явно ввести какую-то вложенную область видимости? Могу ли я зайти так далеко, чтобы зарегистрировать это как ошибку в API ANSYS?
Я сам пытался в этом разобраться, но я не эксперт по дотнетам и не выясняю, смотрю ли я на вариант конфигурации пакета nuget, который мне не подходит, или на старомодный дотнет опция времени выполнения, была очень хитрой.
обновление 1:
Я пытался использовать AppDomain.CreateDomain
, и это действительно решает мою проблему, но также требует от меня предоставления стратегии сортировки для уже загруженных объектов API. Другими словами, если вы программируете на основе плагина, API которого похож на:
public void DoMyPluginsFunctionality(ApiProvidedInputContext context){
var myPlugin = AppDomain.Create(
strongName: "MyCompany.MyPlugin.; Version=1.2.3.4 ...",
baseDirectory: "C:\\Program Files\\MyPlugin\\bin"
)
//success! MyCompany.MyPlugin loads the version of GRPC I want!
myPlugin.unWrapAsDynamicProxy().doFunctionality(context)
//error: No marshalling strategy and/or not serializable and/or swizzling errors
}
Тогда среда выполнения потребует от вас маршалировать (сериализовать) переменную context
, потому что .net не позволит вам совместно использовать память через границы AppDomain.
Итак, мой новый вопрос:
- учитывая, что я не могу использовать AppDomains сам
- учитывая, что Grpc.core всегда публикуется как AssemblyVersion=1.0.0.0
Какие у меня варианты?
- Прекратите использовать новые возможности GRPC.core и живите в страхе перед зависимостями моих родительских процессов
- используйте стратегию, аналогичную затенению . Есть ли что-то вроде затенения в мире .net ?
- Редактировать метаданные версии опубликованного бинарника. Можно ли динамически редактировать опубликованную бинарную версию?
- пересобрать GRPC самостоятельно с обновленной строкой версии - эффективно частной веткой GRPC.
обновление 2:
Система сборки GRPC выглядит довольно большой и в хорошем состоянии, поэтому я надеюсь, что смогу просто собрать ее и изменить файл vcproj, добавив в него обновленную строку версии.
К сожалению, это также кажется довольно сложным, и я не совсем разработал таргетинг / кросс-компиляцию (x64 таргетинг x86).