Как объявить в друзья сборку?

114

В моем решении 2 проекта:

  1. Сборка (базовая библиотека)
  2. Тестовая сборка (NUnit)

Я объявил тестовую сборку как сборку друзей в первом проекте:

[assembly: InternalsVisibleTo ("Company.Product.Tests")]

Все работало нормально, пока я не понял, что забыл настроить решение для подписи моих сборок. Итак, создал файл snk и настроил проект Visual Studio для подписи первой сборки (базовая библиотека). Теперь, когда я компилирую первый проект, я получаю следующую ошибку:

Ссылка на сборку друга "Company.Product.Tests" недействительна. Сборки, подписанные строгим именем, должны указывать открытый ключ в своих объявлениях InternalsVisibleTo.

Я попытался извлечь открытый ключ из своего файла snk с помощью утилиты sn, но она генерирует зашитый двоичный файл, который я не знаю, как использовать. Как я могу решить проблему?

Hemant
источник

Ответы:

194

Вам необходимо подписать обе сборки, поскольку фактически обе сборки ссылаются друг на друга.

Вы должны поместить открытый ключ в атрибут InternalsVisibleTo. Например, в буферах протокола я использую:

[assembly:InternalsVisibleTo("Google.ProtocolBuffers.Test,PublicKey="+
"00240000048000009400000006020000002400005253413100040000010001008179f2dd31a648"+
"2a2359dbe33e53701167a888e7c369a9ae3210b64f93861d8a7d286447e58bc167e3d99483beda"+
"72f738140072bb69990bc4f98a21365de2c105e848974a3d210e938b0a56103c0662901efd6b78"+
"0ee6dbe977923d46a8fda18fb25c65dd73b149a5cd9f3100668b56649932dadd8cf5be52eb1dce"+
"ad5cedbf")]

Открытый ключ можно получить, запустив

sn -Tp path\to\test\assembly.dll

Как вариант, получите его из файла .snk:

sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
Джон Скит
источник
7
И чертовски раздражает то, что в документации MSDN ( msdn.microsoft.com/en-us/library/… ) упоминается смехотворно короткий открытый ключ, который для меня почти похож на токен открытого ключа .
Hemant
3
Вы можете извлечь открытый ключ прямо из файла .snk: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk // sn -tp public.pk //
Тим Лонг
1
Я использовал "заголовок сборки", указанный в AssemblyInfo.cs. С тех пор было установлено, что правильное имя для использования - это «имя сборки» из диалогового окна «Свойства / приложение» проекта (которое снова отличается от имени проекта в обозревателе решений Visual Studio).
Colonel Panic
7
Какими бы полезными ни были эти ответы и комментарии, мне нужно было немного поэкспериментировать, чтобы понять, что открытый ключ - это ключ из сборки, содержащей тесты, а НЕ из сборки, содержащей объявление InternalsInvisibleTo.
Андреас
3
@Andreas: Ну, это соответствует сборке, которую вы называете - вы указываете строгое имя сборки, которой нужно доверять, внутри сборки, которая выполняет доверие.
Джон Скит
-3

Вы можете напрямую получить publicKey из интересующей вас сборки без каких-либо дополнительных действий с помощью sn.exe.

<!-- language: c# -->
var assemblyName = Assembly.GetExecutingAssembly().GetName();
Console.WriteLine("{0}, PublicKey={1}",
    assemblyName.Name,
string.Join("", assemblyName.GetPublicKey().Select(m => string.Format("{0:x2}", m))));
езюзин
источник
1
Это не ответ на этот вопрос. Это должен быть комментарий к ответу, к
Коул Джонсон
-7

Я думаю, вам нужно ввести строгое имя, которое будет примерно таким: «Company.Product.Tests, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = 17135d9fcba0119f». Я предполагаю, что Company.Product.Tests - это ваше имя сборки, а 17135d9fcba0119f - это открытый ключ.

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

user95319
источник
Я не думаю, что нам нужно указывать номер версии и культуру (см. Msdn.microsoft.com/en-us/library/… ). Я действительно не пробовал помещать тестовый код в саму сборку. Постараюсь посмотреть, как это работает (+1 за подсказку).
Hemant
4
Для InternalsVisibleTo PublicKeToken недостаточно. Вам нужен весь открытый ключ :-(
Шон Рейли,