如何将“InternalsVisibleTo”属性与强名称程序集一起使用
本文关键字:程序集 强名称 一起 属性 InternalsVisibleTo | 更新日期: 2023-09-27 17:57:05
我正在使用带有程序集的"InternalsVisibleTo"属性,以向我的单元测试项目公开内部方法/类。
我现在需要将该程序集安装到 GAC 中,因此需要为其指定一个强名称。当我尝试这样做时,我在Visual Studio中收到以下错误。
强名称签名程序集必须在其 InternalsVisibleTo 声明中指定公钥
谷歌搜索把我带到了下面的文章:
https://msdn.microsoft.com/en-us/library/bb763089.aspx
本文指出:
"确定强名称的好友程序集的公钥。"
本文没有说明如何确定公钥。在哪里可以找到程序集的公钥?另外,一旦我有了公钥,这是声明属性的正确方法吗?
[assembly: InternalsVisibleTo("Namespace.Assembly.Example.Name, PublicKey=ThePublicKey")]
2019年5月更新:它与Visual Studio 2019完美配合。
<小时 />2022 年 5 月更新 :正如@Igor梅萨罗斯所提到的,它也适用于 Visual Studio 2022。
<小时 />对于任何使用Visual Studio 2017的人来说,都有最新的方法:
从我们心爱的 IDE 中,转到"工具>外部工具..."和"添加"具有这些设置的新工具:
- 标题 : 获取公钥
- 命令 : "C:''Program Files (x86)''Microsoft SDKs''Windows''v10.0A''bin''NETFX 4.6.2 Tools''sn.exe" (/!'' 选择与您的程序集 NETFX 版本匹配的 NETFX 工具版本,这里是 4.6.2)
- 参数 : -tp $(目标路径)
- 选中"使用输出窗口"复选框
应用/确定这些更改。
在"解决方案资源管理器"中,单击项目程序集名称,然后转到"获取公钥>工具"。"输出"窗口应显示(相当长的)公钥以及公钥密钥。
最后,在包含要公开的内部类(即测试的项目)的项目中,打开"AssemblyInfo.cs"文件并添加以下行:
[汇编:InternalsVisibleTo("MyCompany.SolutionName.ProjectName, PublicKey=将您的公钥粘贴到此处")]
/!'' 您必须从公钥中删除换行符。
它对我来说非常有效,所以希望它也能为你解决问题!
若要将InternalsVisibleTo
与强签名程序集一起使用,您的"友元"程序集也必须进行强签名。需要将测试程序集的公共令牌指定为InternalsVisibleTo
值的一部分。
请注意,该属性不用于编译时程序集的实际验证 - 它仅指定运行时检查(以及友元程序集的编译时检查)应验证该标识。因此,如果您只需要编译主程序集,则可以指定任何公钥标记(例如,在 Web.Config 中的所有程序集引用上找到的 Microsoft 程序集中的一个公钥标记)。
通常,由于您将对程序集进行签名,因此您将知道公钥。 即,如果您有snk文件,则sn -t youSnk.snk
将显示公钥。或者,可以按照在 Visual Studio 中获取程序集的公钥令牌中的步骤将 VS 配置为显示使用 sn -Tp {path to assembly}
从程序集获取公钥的任何程序集的公共令牌。(如果文档消失,步骤将复制到此问题的其他答案)
我使用了经典小说电影中的一个古老的好方法:"黑客总是在第二次尝试中猜测密码"。这是一种简单的技术,除了您已经拥有的工具之外,它不需要任何工具 - 一些单元测试框架。是的,必须对被测程序集进行签名,如此处多次提到。
将下面的此类复制并粘贴到测试 DLL 中。这是 xUnit 测试,但相同的方法适用于任何单元测试框架。
public class FindOutAssemblyPublicKey
{
const string AssemblyPK = "Swordfish";
/// <summary>
/// Fake test to find out a correct PublicKey in InternalsVisibleTo for assembly under test.
/// </summary>
[Fact]
public void AssemblyPublicKeyIsAsExpected()
{
byte[] publicKey = GetType().Assembly.GetName().GetPublicKey();
var sb = new StringBuilder();
foreach (byte @byte in publicKey)
sb.AppendFormat("{0:x2}", @byte);
// Set breakpoint here to find out what's in sb
Assert.Equal(AssemblyPK, sb.ToString());
}
}
这里的想法非常简单:测试在第一次运行时失败,但显示测试程序集的正确公钥。要仔细检查将"剑鱼"替换为您获得的实际值,请再次运行测试以确保它是绿色的并且您在这里。