Bagaimana cara mendeklarasikan pertemuan teman?

114

Saya memiliki 2 proyek dalam solusi saya:

  1. Majelis (Perpustakaan Dasar)
  2. Majelis Uji (NUnit)

Saya telah menyatakan perakitan tes sebagai perakitan teman di proyek pertama:

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

Semuanya berfungsi dengan baik sampai saya menyadari bahwa saya lupa menyiapkan solusi untuk menandatangani majelis saya. Jadi buat file snk dan atur proyek studio visual untuk menandatangani perakitan pertama (Perpustakaan Dasar). Sekarang ketika saya mengkompilasi proyek pertama, saya mendapatkan kesalahan berikut:

Referensi perakitan teman 'Company.Product.Tests' tidak valid. Rakitan bertanda tangan nama kuat harus menentukan kunci publik dalam deklarasi InternalsVisibleTo mereka.

Saya mencoba mengekstrak kunci publik dari file snk saya menggunakan utilitas sn tetapi menghasilkan file biner berkabel yang saya tidak yakin cara menggunakannya. Bagaimana cara mengatasi masalah tersebut?

Hemant
sumber

Jawaban:

194

Anda perlu menandatangani kedua majelis, karena secara efektif kedua majelis saling merujuk.

Anda harus meletakkan kunci publik di atribut InternalsVisibleTo. Misalnya, dalam Protocol Buffer saya menggunakan:

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

Kunci publik diambil dengan menjalankan

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

Atau, dapatkan dari file .snk:

sn -p MyStrongnameKey.snk public.pk
sn -tp public.pk
Jon Skeet
sumber
7
Dan sangat menjengkelkan melihat dokumentasi MSDN ( msdn.microsoft.com/en-us/library/… ) menyebutkan kunci publik yang sangat pendek yang hampir terlihat seperti token kunci publik bagi saya.
Hemant
3
Anda dapat mengekstrak kunci publik langsung dari file .snk: sn -k MyStrongnameKey.snk // sn -p MyStrongnameKey.snk public.pk // sn -tp public.pk //
Tim Long
1
Saya menggunakan 'judul perakitan' yang ditentukan dalam AssemblyInfo.cs. Sejak itu disimpulkan nama yang tepat untuk digunakan adalah 'nama perakitan' dari dialog Properti / Aplikasi proyek (yang berbeda lagi dari nama proyek di penjelajah solusi Visual Studio).
Kolonel Panic
7
Meskipun jawaban dan komentar ini sangat membantu, saya memerlukan beberapa eksperimen untuk menyadari bahwa kunci publik adalah kunci dari rakitan yang berisi tes, BUKAN rakitan yang berisi deklarasi 'InternalsInvisibleTo'.
Andreas
3
@Andreas: Baik itu sejalan dengan majelis yang Anda beri nama - Anda menentukan nama kuat majelis untuk dipercaya, di dalam majelis yang melakukan kepercayaan.
Jon Skeet
-3

Anda bisa langsung mendapatkan publicKey dari assembly yang Anda minati, tanpa sihir dengan 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
sumber
1
Ini bukanlah jawaban untuk pertanyaan ini . Ini harus menjadi komentar atas jawaban yang ditujukan
Cole Johnson
-7

Saya rasa Anda perlu memasukkan nama yang kuat, yang akan menjadi seperti "Company.Product.Tests, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 17135d9fcba0119f". Saya menganggap Company.Product.Tests adalah nama perakitan Anda dan 17135d9fcba0119f adalah kunci publik.

Cara lain untuk menyelesaikan masalah ini adalah dengan tidak menggunakan rakitan terpisah. Saya biasanya meletakkan kode sumber dan kode pengujian dalam perakitan yang sama. Saya tidak tahu apakah Anda memiliki perhatian khusus sehingga Anda harus memisahkan mereka.

pengguna95319
sumber
Saya rasa kita tidak perlu menentukan nomor versi dan budaya (lihat msdn.microsoft.com/en-us/library/… ). Saya belum benar-benar mencoba menempatkan kode uji di rakitan itu sendiri. Akan mencoba dan melihat cara kerjanya (+1 untuk tip).
Hemant
4
Untuk InternalsVisibleTo, PublicKeToken tidak cukup. Anda memerlukan seluruh kunci publik :-(
Sean Reilly