Сборка C# со строгими именами и ссылками со слабыми именами работает в одном контексте, но не в другом

#c# #.net

Вопрос:

Краткие сведения

Я разрабатываю мод для видеоигры на C#. Я также разрабатываю библиотеку утилит для модов для этой видеоигры, которую я хотел бы использовать в своем моде. По тем причинам, которые я считаю вескими*, библиотека утилит имеет строгое название. Это прекрасно работает, когда я загружаю его в игру, но когда я пытаюсь запустить модульные тесты NUnit компонентов мода, которые используют библиотеку утилит, я получаю сбои при загрузке сборок для сборок, на которые ссылается библиотека утилит. Я хотел бы каким-то образом запустить модульные тесты с помощью служебной библиотеки со строгими именами или, в противном случае, использовать какой-либо другой механизм для повторного использования кода между двумя модами для этой игры, который не столкнется с проблемами сборки со строгими именами.

Что представляют собой все эти ассамблеи, участвующие здесь?

GameEngine.dll это сборка в игре, которую я моддирую. Он содержит типы и методы, центральные для игры, которые необходимо использовать, чтобы заставить мод делать модные вещи. Я не могу контролировать его или его поведение. У него нет строгого названия.

Mod.dll это центральная сборка для мода, который я разрабатываю. В нем есть ссылки на GameEngine.dll и UtilityLibrary.dll. У него нет строгого названия.

Utilities.dll содержит полезные функции и типы, которые широко полезны для нескольких модов игры. Я его разрабатываю. В нем есть ссылки на GameEngine.dll. Он сильно назван по причинам, обсуждаемым ниже.

ModUnitTests.dll представляет собой набор модульных тестов NUnit моего мод-кода. Я его разрабатываю. В нем есть ссылки на GameEngine.dll и Mod.dll.

Это все .Net Framework 3.5 для всего, кроме ModUnitTests, который равен 4.0.

В чем конкретно заключается проблема?

Когда я загружаю мод в игру, все загружается нормально и Mod.dll может использовать вещи из Utilities.dll. Несколько модов, ссылающихся на разные версии утилит.dll загружается нормально и использует типы и методы из своей версии сборки.

Но когда я запускаю модульные тесты, которые используют утилиты.функции dll, программа выходит из строя, и я получаю сообщение об ошибке System.IO.FileLoadException: 'Could not load file or assembly 'GameEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044) . Если Коммунальные услуги.dll не имеет строгого названия, все работает. Насколько я понимаю, я получаю эту ошибку из-за утилит со строгими именами.dll пытается загрузить программу со слабым именем GameEngine.dll, и это недопустимо. Но если это так, то почему это работает в игре?

Почему ассамблея имеет строгое название?

(Или: «Просто перестань бить себя»). Если два разных мода используют утилиты.dll и загружаются в игру, второй мод для загрузки получит типы и функции из утилит.dll входит в комплект первого мода. Если версии не совпадают, это приведет к сбиванию с толку. Обычная проблема с DLL-адом.

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

Я знаю о проблемах, которые могут возникнуть, если Mod1 загружает Utility1, Mod2 загружает Utility2, а затем Mod1 передает тип из Utility1 в Mod2. Из-за того, как игра структурирована и моды работают для игры, это не должно вызывать беспокойства, и, во всяком случае, это все равно лучше, чем ситуация, когда Mod2 с самого начала получает Полезность1.

Помогите!

То, что я ищу,-это либо решение для загрузки и запуска тестов Modunittest, даже если утилиты со строгими именами.dll ссылается на слабо названную GameEngine.dll. Похоже, это работает при запуске в игре, так что это, по крайней мере, теоретически возможно.

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

Комментарии:

1. Конечно, одна очевидная идея состоит в том, чтобы просто сохранить версию служебной библиотеки со слабым именем для модульных тестов и использовать версию со строгим именем для внешнего распространения; это подвержено ошибкам и отчасти ужасно, но должно работать. Я больше всего беспокоюсь о том, что настройка, которая, по-видимому, работает в игре, является иллюзией, и есть проблема, которую я упускаю.

2. Согласно вашим комментариям, проверка строгого имени не выполняется при загрузке сборок в игре (это может произойти, например, если игровой движок выполняет пользовательский хостинг CLR и переопределяет загрузку сборок, что вполне вероятно). Таким образом, строгое именование библиотеки DLL утилит также не приведет к достижению того, чего вы хотите. За исключением случаев, когда проверка отключена, сборки со слабыми именами не могут загружать сборки со строгими именами, поэтому независимо от того, как вы их срежете, вы не сможете использовать строгие имена.

3. Я проверил, что в случае Mod1-gt;Utility1 / Mod2-gt;gt;Utility2 все ведет себя так, как я ожидаю в игре; Mod1 получает поведение Utility1; Mod2 получает поведение Utility2. На самом деле я получаю от этого то, что хочу.

4. Итак, вы убедились, что этого не произойдет, если обе версии не используют строгие имена?

5. Вы должны заставить дистрибьютора игр распространять сборки со строгими именами. Ни одна общедоступная сборка больше не должна выпускаться без строгих имен.