如何使用" InternalsVisibleTo"具有强名称汇编的属性?

时间:2015-06-19 16:51:58

标签: c# .net-assembly

我正在使用" InternalsVisibleTo"带有程序集的属性,用于将内部方法/类公开给我的单元测试项目。

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

  

强名称签名程序集必须在其InternalsVisibleTo声明

中指定公钥

谷歌的一点点让我看到了下面的文章:

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

本文指出:

  

"确定强名友人程序集的公钥。"

本文未说明如何确定公钥。我在哪里可以找到装配的公钥?此外,一旦我有公钥,这是否是声明属性的正确方法?

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

4 个答案:

答案 0 :(得分:42)

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

对于使用Visual Studio 2017的任何人,都有最新的方法:

从我们心爱的IDE中,转到" 工具>外部工具...... "和" 添加"这些设置的新工具:

  • 标题:获取PublicKey
  • 命令:" C:\ Program Files(x86)\ Microsoft SDKs \ Windows \ v10.0A \ bin \ NETFX 4.6.2 Tools \ sn.exe " (/!\选择与您的程序集NETFX版本匹配的NETFX工具版本,此处为4.6.2)
  • 参数: -Tp $(TargetPath)
  • 检查"使用输出窗口"复选框

应用/确定这些更改。

在"解决方案资源管理器" 点击您的项目程序集名称,然后前往" 工具>获取PublicKey "。 “输出”窗口应显示(很长)公钥以及公共令牌密钥。

最后,在包含要公开的内部类(即测试项目)的项目中,打开" AssemblyInfo.cs "文件并添加以下行:

[assembly:InternalsVisibleTo(" MyCompany.SolutionName.ProjectName,PublicKey = 将您的公钥粘贴到此处")]

/!\您必须从公钥中删除换行符。

它对我来说非常有用,所以希望它能为你做到这一点!

答案 1 :(得分:17)

使用InternalsVisibleTo与强烈签名的汇编你的朋友"程序集也必须强烈签名。需要将测试程序集的公共标记指定为InternalsVisibleTo值的一部分。

请注意,该属性在编译时不用于程序集的实际验证 - 它仅指定运行时检查(以及朋友程序集的编译时检查)应验证该标识。因此,如果 需要编译主程序集,则可以指定任何公钥标记(例如,在Web.Config中的所有程序集引用中找到的Microsoft组件中的一个)。

通常,因为您要签署程序集,所以您知道公钥。即如果您有snk文件,则sn -t youSnk.snk将显示公钥。或者,您可以按照Getting Public Key Token of Assembly Within Visual Studio中的步骤配置VS,以显示使用sn -Tp {path to assembly}从程序集获取公钥的任何程序集的公共令牌。 (如果文档已经过去,则将步骤复制到other answer to this question

答案 2 :(得分:1)

如果您没有测试发布配置,这是一个简单的解决方法:

#if DEBUG
[assembly: InternalsVisibleTo("TestProjNamespace")]
#endif

答案 3 :(得分:0)

我使用经典小说电影中的一个古老的好方法:“黑客总是在第二次尝试中猜测密码”。这是一种简单的技术,除了您已有的工具之外,不需要任何工具 - 一些单元测试框架。是的,必须对被测组件进行签名,正如这里多次提到的那样。

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

这里的想法很简单:测试在第一次运行时失败,但会显示测试程序集的正确公钥。要仔细检查是否将“Swordfish”替换为您所获得的实际值,请第二次运行测试以确保它是绿色的,您就在这里。