จะประกาศการชุมนุมของเพื่อนได้อย่างไร?


114

ฉันมี 2 โครงการในโซลูชันของฉัน:

  1. แอสเซมบลี (ห้องสมุดพื้นฐาน)
  2. ชุดทดสอบ (NUnit)

ฉันได้ประกาศชุดทดสอบเป็นชุดเพื่อนในโครงการแรก:

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

ทุกอย่างทำงานได้ดีจนกระทั่งฉันรู้ว่าฉันลืมตั้งค่าโซลูชันเพื่อลงนามในชุดประกอบของฉัน ดังนั้นจึงสร้างไฟล์ snk และตั้งค่าโปรเจ็กต์ visual studio เพื่อลงนามในแอสเซมบลีแรก (Basic Library) ตอนนี้เมื่อฉันรวบรวมโปรเจ็กต์แรกฉันได้รับข้อผิดพลาดต่อไปนี้:

ข้อมูลอ้างอิงการประกอบเพื่อน 'Company.Product.Tests' ไม่ถูกต้อง แอสเซมบลีที่เซ็นชื่อรัดกุมต้องระบุคีย์สาธารณะในการประกาศ InternalsVisibleTo

ฉันพยายามแยกคีย์สาธารณะจากไฟล์ snk ของฉันโดยใช้ยูทิลิตี้ sn แต่มันสร้างไฟล์ไบนารีแบบมีสายซึ่งฉันไม่แน่ใจว่าจะใช้อย่างไร ฉันจะแก้ไขปัญหาได้อย่างไร?

คำตอบ:


194

คุณต้องลงนามในแอสเซมบลีทั้งสองเนื่องจากแอสเซมบลีทั้งสองอ้างอิงกันอย่างมีประสิทธิภาพ

คุณต้องใส่คีย์สาธารณะในแอตทริบิวต์ InternalsVisibleTo ตัวอย่างเช่นใน Protocol Buffers ฉันใช้:

[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 //
Tim Long

1
ฉันใช้ 'ชื่อการชุมนุม' ที่ระบุในAssemblyInfo.cs. ตั้งแต่นั้นมาได้อนุมานชื่อที่เหมาะสมที่จะใช้คือ 'ชื่อแอสเซมบลี' จากกล่องโต้ตอบคุณสมบัติ / แอปพลิเคชันของโครงการ (ซึ่งแตกต่างจากชื่อโครงการในตัวสำรวจโซลูชันของ Visual Studio อีกครั้ง)
พันเอก Panic

7
ในฐานะที่เป็นคำตอบและความคิดเห็นเหล่านี้จะเป็นประโยชน์ฉันจึงต้องการการทดลองบางอย่างเพื่อให้ตระหนักว่าคีย์สาธารณะเป็นคีย์จากชุดประกอบที่มีการทดสอบไม่ใช่แอสเซมบลีที่มีการประกาศ 'InternalsInvisibleTo'
Andreas

3
@ แอนเดรียส: มันเข้ากันได้ดีกับแอสเซมบลีที่คุณกำลังตั้งชื่อ - คุณกำลังระบุชื่อที่แข็งแกร่งของแอสเซมบลีที่จะเชื่อถือได้ภายในแอสเซมบลีที่ให้ความไว้วางใจ
Jon Skeet

-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
นี้ไม่ได้เป็นคำตอบกับผู้นี้คำถาม ควรเป็นความคิดเห็นเกี่ยวกับคำตอบที่อยู่
Cole Johnson

-7

ฉันคิดว่าคุณต้องใส่ชื่อที่ชัดเจนซึ่งจะเป็นเช่น "Company.Product.Tests, เวอร์ชัน = 1.0.0.0, วัฒนธรรม = เป็นกลาง, PublicKeyToken = 17135d9fcba0119f" ฉันถือว่า Company.Product.Tests คือชื่อแอสเซมบลีของคุณและ 17135d9fcba0119f คือคีย์สาธารณะ

อีกวิธีหนึ่งในการแก้ไขปัญหานี้คือไม่ใช้ชุดประกอบแยกกัน ฉันมักจะใส่ซอร์สโค้ดและโค้ดทดสอบในแอสเซมบลีเดียวกัน ฉันไม่รู้ว่าคุณกังวลอะไรเป็นพิเศษที่ต้องแยกพวกเขาออกจากกัน


ฉันไม่คิดว่าเราจำเป็นต้องระบุหมายเลขเวอร์ชันและวัฒนธรรม (ดูmsdn.microsoft.com/en-us/library/… ) ฉันยังไม่ได้ลองใส่รหัสทดสอบในชุดประกอบ จะลองดูวิธีการทำงาน (+1 สำหรับทิป).
Hemant

4
สำหรับ InternalsVisibleTo PublicKeToken นั้นไม่เพียงพอ คุณต้องมีคีย์สาธารณะทั้งหมด :-(
Sean Reilly
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.