如何将 "InternalsVisibleTo" 属性与强命名程序集一起使用?

How to use "InternalsVisibleTo" attribute with Strongly named assembly?

我将 "InternalsVisibleTo" 属性与程序集一起使用,以将内部 methods/classes 公开给我的单元测试项目。

我现在需要将该程序集安装到 GAC 中,因此我需要为其指定一个强名称。当我尝试这样做时,我在 Visual Studio 中收到以下错误。

Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations

通过谷歌搜索,我找到了以下文章:

https://msdn.microsoft.com/en-us/library/bb763089.aspx

本文指出:

"Determine the public key for the strong-named friend assembly."

本文没有说如何确定public键。在哪里可以找到程序集的 public 键?另外,一旦我有了 public 键,这是声明属性的正确方法吗?

[assembly: InternalsVisibleTo("Namespace.Assembly.Example.Name, PublicKey=ThePublicKey")]

要将 InternalsVisibleTo 与强签名程序集一起使用,您的“朋友”程序集也必须是强签名的。 Public 测试程序集的令牌需要指定为 InternalsVisibleTo 值的一部分。

请注意,该属性不用于编译时程序集的实际验证 - 它仅指定 运行 时检查(以及朋友程序集的编译时检查)应该验证该身份。因此,如果您 只是 需要编译您的主程序集,您可以指定任何 public 密钥令牌(即来自 Web.Config 中所有程序集引用的 Microsoft 程序集之一例如)。

通常,因为您要签署程序集,所以您会知道 public 密钥。 IE。如果你有 snk 文件,那么 sn -t youSnk.snk 会显示 public 键。或者您可以按照 Getting Public Key Token of Assembly Within Visual Studio to configure your VS to show public token for any assembly which uses sn -Tp {path to assembly} to get public key from the assembly. (If document is gone steps are copied to the )

中的步骤操作

2019 年 5 月更新: 它与 Visual Studio 2019 完美配合。


2022 年 5 月更新: 如@Igor Meszaros 所述,它也适用于 Visual Studio 2022。


对于正在使用 Visual Studio 2017 的任何人,这里有最新的方法:

来自我们心爱的 IDE,转到“工具 > 外部工具...”和“添加”具有这些设置的新工具:

  • 标题:获取Public密钥
  • 命令:“C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\sn.exe” (/!\ 选择与您的程序集 NETFX 版本匹配的 NETFX 工具版本,这里是 4.6.2)
  • 参数:-Tp $(TargetPath)
  • 选中“使用输出 window”复选框

Apply/OK 那些变化。

在“解决方案资源管理器”中 单击您的项目程序集名称,然后转到“工具 > 获取 Public密钥”。 输出 window 应该显示(很长)Public 密钥,以及 Public 令牌密钥。

最后,在你要暴露的包含内部class的项目(即测试项目)中,打开“AssemblyInfo.cs”文件并添加行:

[程序集:InternalsVisibleTo("MyCompany.SolutionName.ProjectName, PublicKey=在此处粘贴您的 public 键") ]

/!\ 您必须从 public 键中删除换行符。

它对我来说效果很好,所以希望它对你也有帮助!

我使用了 class 科幻电影中的一个古老的好方法:“黑客总是在第二次尝试中猜测密码”。这是一种简单的技术,除了您已经拥有的一些单元测试框架之外,它不需要任何工具。是的,必须对被测程序集进行签名,如此处多次提及。

复制下面的 class 并将其粘贴到您的测试 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());
    }
}

这里的想法很简单:一开始测试失败 运行 但会显示测试程序集的正确 public 密钥。要仔细检查用您得到的实际值替换“Swordfish”,运行 第二次测试以确保它是绿色的,这就是您的位置。