Jak zgłosić zgromadzenie przyjaciela?

114

W swoim rozwiązaniu mam 2 projekty:

  1. Zespół (biblioteka podstawowa)
  2. Zespół testowy (NUnit)

Zadeklarowałem montaż testowy jako zespół przyjaciół w pierwszym projekcie:

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

Wszystko działało dobrze, aż zdałem sobie sprawę, że zapomniałem skonfigurować rozwiązanie do podpisywania moich zestawów. Utworzono więc plik snk i skonfigurowano projekt Visual Studio, aby podpisać pierwszy zestaw (biblioteka podstawowa). Teraz, kiedy kompiluję pierwszy projekt, pojawia się następujący błąd:

Odwołanie do zestawu znajomego „Company.Product.Tests” jest nieprawidłowe. Podpisane zestawy o silnej nazwie muszą określać klucz publiczny w swoich deklaracjach InternalsVisibleTo.

Próbowałem wyodrębnić klucz publiczny z mojego pliku snk za pomocą narzędzia sn, ale generuje on przewodowy plik binarny, którego nie jestem pewien, jak go użyć. Jak mogę rozwiązać problem?

Hemant
źródło

Odpowiedzi:

194

Musisz podpisać oba zestawy, ponieważ efektywnie oba zestawy odwołują się do siebie.

Musisz umieścić klucz publiczny w atrybucie InternalsVisibleTo. Na przykład w Protocol Buffers używam:

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

Klucz publiczny jest pobierany przez uruchomienie

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

Możesz też pobrać go z pliku .snk:

sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
Jon Skeet
źródło
7
I cholernie irytujące jest zobaczenie dokumentacji MSDN ( msdn.microsoft.com/en-us/library/ ), w której wspomina się o absurdalnie krótkim kluczu publicznym, który dla mnie wygląda prawie jak token klucza publicznego .
Hemant,
3
Możesz wyodrębnić klucz publiczny bezpośrednio z pliku .snk: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk // sn -tp public.pk //
Tim Long
1
Używałem „tytułu zespołu” określonego w AssemblyInfo.cs. Od tamtej pory właściwą nazwą do użycia jest `` nazwa zestawu '' z okna dialogowego Właściwości / Aplikacja projektu (która ponownie różni się od nazwy projektu w eksploratorze rozwiązań programu Visual Studio).
Colonel Panic
7
Chociaż te odpowiedzi i komentarze były pomocne, potrzebowałem trochę eksperymentów, aby zdać sobie sprawę, że klucz publiczny to ten z zestawu zawierającego testy, a NIE zestaw zawierający deklarację „InternalsInvisibleTo”.
Andreas
3
@Andreas: Cóż, idzie to w parze z zestawem, który nazywasz - określasz silną nazwę zestawu, któremu chcesz zaufać, w ramach zespołu, który ufał.
Jon Skeet,
-3

Możesz bezpośrednio pobrać publicKey z zestawu, który Cię interesuje, bez magii za pomocą 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))));
ezyuzin
źródło
1
To nie jest odpowiedź na to pytanie. Powinien to być komentarz do odpowiedzi, do której się odnosi
Cole Johnson,
-7

Myślę, że musisz wpisać silną nazwę, która brzmiałaby jak „Firma.Product.Tests, Wersja = 1.0.0.0, Kultura = neutralna, PublicKeyToken = 17135d9fcba0119f”. Zakładam, że Company.Product.Tests to nazwa twojego zestawu, a 17135d9fcba0119f to klucz publiczny.

Innym sposobem rozwiązania tego problemu byłoby nieużywanie oddzielnych zestawów. Zwykle umieszczam kod źródłowy i kod testowy w tym samym zestawie. Nie wiem, czy masz jakieś szczególne obawy, że musisz je rozdzielić.

user95319
źródło
Nie sądzę, abyśmy musieli określać numer wersji i kulturę (patrz msdn.microsoft.com/en-us/library/ ... ). Naprawdę nie próbowałem umieszczać kodu testowego w samym zestawie. Spróbuję i zobaczę, jak to działa (+1 za napiwek).
Hemant,
4
W przypadku InternalsVisibleTo PublicKeToken nie wystarczy. Potrzebujesz całego klucza publicznego :-(
Sean Reilly,