我正在尝试使用InternalsVisibleTo
assembly属性使我的单元测试项目可以看到.NET类库中的内部类.出于某种原因,我不断收到一条错误消息:
由于其保护级别,"MyClassName"无法访问
两个程序集都已签名,并且我在属性声明中列出了正确的密钥.有任何想法吗?
您确定要在属性中指定正确的公钥吗?请注意,您需要指定完整的公钥,而不仅仅是公钥标记.它看起来像:
[assembly: InternalsVisibleTo("MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73 F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66 A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519 674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140 6E2F553073FF557D2DB6C5")]
它是320左右的十六进制数字.不确定为什么需要指定完整的公钥 - 可能只使用其他程序集引用中使用的公钥标记,这样可以更容易欺骗朋友程序集的标识.
另一个可能的"问题":您在其中指定的朋友程序集的名称InternalsVisibleToAttribute
必须与朋友程序集的名称完全匹配,如朋友的项目属性中所示(在"应用程序"选项卡中).
就我而言,我有一个项目Thingamajig
和一个伴侣项目ThingamajigAutoTests
(名称已更改以保护有罪),这两个项目都生成了未签名的程序集.我适当添加的属性[assembly: InternalsVisibleTo( "ThingamajigAutoTests" )]
到Thingamajig\AssemblyInfo.cs文件,并评论出AssemblyKeyFile
和AssemblyKeyName
如上所述的属性.该Thingamajig
项目建设得很好,但其内部成员顽固地拒绝出现在自动测试项目中.
经过多次努力,我重新检查了ThingamajigAutoTests
项目属性,发现程序集名称被指定为"ThingamajigAutoTests.dll".宾果游戏 - 我在InternalsVisibleTo
属性中的程序集名称中添加了".dll"扩展名,并且这些部分已经到位.
有时它是最小的东西......
如果您的程序集未签名,但仍然遇到相同的错误,请检查AssemblyInfo.cs文件中是否有以下任一行:
[assembly: AssemblyKeyFile("")] [assembly: AssemblyKeyName("")]
如果存在这些行中的任何一行(或两者),则属性选项卡仍会将程序集显示为无符号,但InternalsVisibleTo属性将具有这些行的程序集视为强签名.只需删除(或注释掉)这些行,它就可以正常工作了.
值得注意的是,如果"朋友"(测试)程序集是用C++/CLI编写的,而不是C#/ VB.Net那么你需要使用以下代码:
#using "AssemblyUnderTest.dll" as_friend
而不是项目参考或通常的#using
声明.出于某种原因,在项目参考UI中无法执行此操作.
您可以使用AssemblyHelper工具为您生成InternalsVisibleTo语法.这是最新版本的链接.请注意,它仅适用于强名称程序集.
这是我用来快速生成此属性的宏.它有点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