当前位置:  开发笔记 > 编程语言 > 正文

InternalsVisibleTo属性不起作用

如何解决《InternalsVisibleTo属性不起作用》经验,为你挑选了6个好方法。

我正在尝试使用InternalsVisibleToassembly属性使我的单元测试项目可以看到.NET类库中的内部类.出于某种原因,我不断收到一条错误消息:

由于其保护级别,"MyClassName"无法访问

两个程序集都已签名,并且我在属性声明中列出了正确的密钥.有任何想法吗?



1> Joe..:

您确定要在属性中指定正确的公钥吗?请注意,您需要指定完整的公钥,而不仅仅是公钥标记.它看起来像:

[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]

它是320左右的十六进制数字.不确定为什么需要指定完整的公钥 - 可能只使用其他程序集引用中使用的公钥标记,这样可以更容易欺骗朋友程序集的标识.


获取朋友程序集的公钥"sn -Tp MyFriendAssembly"
这方面的MSDN文档为-1000,但仍然不完整.
要澄清@Ian G的注释,请打开Visual Studio命令提示符,将目录(CD)更改为包含"朋友"程序集dll文件的相关目录.在命令提示符下,输入`sn.exe -Tp NameOfAssembly`,或者只是`sn -Tp NameOfAssembly`,如Ian所说.这使用Microsoft的强名称工具查找并显示程序集中的完整公钥.如果您只有一个包含密钥的.pub文件,则可以使用`sn.exe -p NameOfKeyFile.snk NameOfKeyPairFile.pub`来提取它.这将创建NameOfKeyFile.snk密钥文件,这将使您能够遵循先前的说明.
非常重要的是,至少在VS2012中,`[assembly:InternalsVisibleTo("...")]`属性**必须在一行**上,尽管这里的示例和MSDN文档中有明显的格式.你不能只是从`sn.exe -Tp MyFriendAssembly`复制粘贴公钥输出,然后使用`@"多行字符串"`(注意@ -character)或编译器会抱怨`...不包含"X"的定义,并且在尝试从MyFriendAssembly访问您的内部时,无法找到扩展方法'X'...

2> John Beyer..:

另一个可能的"问题":您在其中指定的朋友程序集的名称InternalsVisibleToAttribute必须与朋友程序集的名称完全匹配,如朋友的项目属性中所示(在"应用程序"选项卡中).

就我而言,我有一个项目Thingamajig和一个伴侣项目ThingamajigAutoTests(名称已更改以保护有罪),这两个项目都生成了未签名的程序集.我适当添加的属性[assembly: InternalsVisibleTo( "ThingamajigAutoTests" )]到Thingamajig\AssemblyInfo.cs文件,并评论出AssemblyKeyFileAssemblyKeyName如上所述的属性.该Thingamajig项目建设得很好,但其内部成员顽固地拒绝出现在自动测试项目中.

经过多次努力,我重新检查了ThingamajigAutoTests项目属性,发现程序集名称被指定为"ThingamajigAutoTests.dll".宾果游戏 - 我在InternalsVisibleTo属性中的程序集名称中添加了".dll"扩展名,并且这些部分已经到位.

有时它是最小的东西......


+1,因为你的评论帮助了我:在我的情况下,我已经在某个时候重命名了程序集,但是VS已经将Project Properties中的程序集名称和默认名称空间保留为旧值
嗯 对我来说正好相反。我必须删除“ .dll”才能构建解决方案。

3> 小智..:

如果您的程序集未签名,但仍然遇到相同的错误,请检查AssemblyInfo.cs文件中是否有以下任一行:

[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

如果存在这些行中的任何一行(或两者),则属性选项卡仍会将程序集显示为无符号,但InternalsVisibleTo属性将具有这些行的程序集视为强签名.只需删除(或注释掉)这些行,它就可以正常工作了.



4> Colin Desmon..:

值得注意的是,如果"朋友"(测试)程序集是用C++/CLI编写的,而不是C#/ VB.Net那么你需要使用以下代码:

#using "AssemblyUnderTest.dll" as_friend

而不是项目参考或通常的#using声明.出于某种原因,在项目参考UI中无法执行此操作.



5> Vadim..:

您可以使用AssemblyHelper工具为您生成InternalsVisibleTo语法.这是最新版本的链接.请注意,它仅适用于强名称程序集.



6> 小智..:

这是我用来快速生成此属性的宏.它有点hacky,但它的工作原理.在我的机器上.当最新签名的二进制文件在/bin/debug.时 Etc模棱两可等等.无论如何,你可以看到它是如何获得密钥的,所以它会给你一个提示.随着时间的推移,修复/改进.

Sub GetInternalsVisibleToForCurrentProject()
    Dim temp = "[assembly:  global::System.Runtime.CompilerServices." + _
               "InternalsVisibleTo(""{0}, publickey={1}"")]"
    Dim projs As System.Array
    Dim proj As Project
    projs = DTE.ActiveSolutionProjects()
    If projs.Length < 1 Then
        Return
    End If

    proj = CType(projs.GetValue(0), EnvDTE.Project)
    Dim path, dir, filename As String
    path = proj.FullName
    dir = System.IO.Path.GetDirectoryName(path)
    filename = System.IO.Path.GetFileNameWithoutExtension(path)
    filename = System.IO.Path.ChangeExtension(filename, "dll")
    dir += "\bin\debug\"
    filename = System.IO.Path.Combine(dir, filename)
    If Not System.IO.File.Exists(filename) Then
        MsgBox("Cannot load file " + filename)
        Return
    End If
    Dim assy As System.Reflection.Assembly
    assy = System.Reflection.Assembly.Load(filename)
    Dim pk As Byte() = assy.GetName().GetPublicKey()
    Dim hex As String = BitConverter.ToString(pk).Replace("-", "")
    System.Windows.Forms.Clipboard.SetText(String.Format(temp, assy.GetName().Name, hex))
    MsgBox("InternalsVisibleTo attribute copied to the clipboard.")
End Sub

推荐阅读
小白也坚强_177
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有