.net InternalsVisibleTo 属性不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/106880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
InternalsVisibleTo attribute isn't working
提问by skb
I am trying to use the InternalsVisibleToassembly attribute to make my internal classes in a .NET class library visible to my unit test project. For some reason, I keep getting an error message that says:
我正在尝试使用InternalsVisibleTo程序集属性使 .NET 类库中的内部类对我的单元测试项目可见。出于某种原因,我不断收到一条错误消息,内容为:
'MyClassName' is inaccessible due to its protection level
'MyClassName' 由于其保护级别而无法访问
Both assemblies are signed and I have the correct key listed in the attribute declaration. Any ideas?
两个程序集都已签名,并且我在属性声明中列出了正确的密钥。有任何想法吗?
回答by Joe
Are you absolutely sure you have the correct public key specified in the attribute? Note that you need to specify the full public key, not just the public key token. It looks something like:
您确定您在属性中指定了正确的公钥吗?请注意,您需要指定完整的公钥,而不仅仅是公钥令牌。它看起来像:
[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]
It's 320 or so hex digits. Not sure why you need to specify the full public key - possibly with just the public key token that is used in other assembly references it would be easier for someone to spoof the friend assembly's identity.
它是 320 个左右的十六进制数字。不确定为什么需要指定完整的公钥 - 可能只使用在其他程序集引用中使用的公钥令牌,有人会更容易欺骗朋友程序集的身份。
回答by John Beyer
Another possible "gotcha": The name of the friend assembly that you specify in the InternalsVisibleToAttributemust exactlymatch the name of your friend assembly as shown in the friend's project properties (in the Application tab).
另一个可能的“问题”:您在 中指定的朋友程序集的名称InternalsVisibleToAttribute必须与朋友程序集的名称完全匹配,如朋友的项目属性(在应用程序选项卡中)所示。
In my case, I had a project Thingamajigand a companion project ThingamajigAutoTests(names changed to protect the guilty) that both produced unsigned assemblies. I duly added the attribute [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )]to the Thingamajig\AssemblyInfo.cs file, and commented out the AssemblyKeyFileand AssemblyKeyNameattributes as noted above. The Thingamajigproject built just fine, but its internal members stubbornly refused to show up in the autotest project.
就我而言,我有一个项目Thingamajig和一个配套项目ThingamajigAutoTests(名称已更改以保护有罪的人),它们都生成了未签名的程序集。我适当地将属性添加[assembly: InternalsVisibleTo( "ThingamajigAutoTests" )]到 Thingamajig\AssemblyInfo.cs 文件中,并注释掉了上面提到的AssemblyKeyFile和AssemblyKeyName属性。该Thingamajig项目构建得很好,但其内部成员顽固地拒绝出现在自动测试项目中。
After much head scratching, I rechecked the ThingamajigAutoTestsproject properties, and discovered that the assembly name was specified as "ThingamajigAutoTests.dll". Bingo - I added the ".dll" extension to the assembly name in the InternalsVisibleToattribute, and the pieces fell into place.
经过ThingamajigAutoTests一番摸索,我重新检查了项目属性,发现程序集名称被指定为“ThingamajigAutoTests.dll”。Bingo - 我在InternalsVisibleTo属性中为程序集名称添加了“.dll”扩展名,然后各个部分就位。
Sometimes it's the littlest things...
有时它是最小的事情......
回答by Skimedic
If your assemblies aren't signed, but you are still getting the same error, check your AssemblyInfo.cs file for either of the following lines:
如果您的程序集未签名,但您仍然遇到相同的错误,请检查您的 AssemblyInfo.cs 文件是否包含以下任一行:
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
The properties tab will still show your assembly as unsigned if either (or both) of these lines are present, but the InternalsVisibleTo attribute treats an assembly with these lines as strongly signed. Simply delete (or comment out) these lines, and it should work fine for you.
如果存在这些行中的任何一行(或两者),则属性选项卡仍将您的程序集显示为未签名,但 InternalsVisibleTo 属性将具有这些行的程序集视为强签名。只需删除(或注释掉)这些行,它应该适合您。
回答by Colin Desmond
It is worth noting that if the "friend" (tests) assembly it is written in C++/CLI, rather than C#/VB.Net then you need to use the following:
值得注意的是,如果“朋友”(测试)程序集是用 C++/CLI 而不是 C#/VB.Net 编写的,那么您需要使用以下内容:
#using "AssemblyUnderTest.dll" as_friend
instead of a project reference or the usual #usingstatement. For some reason, there is no way to do this in the project reference UI.
而不是项目参考或通常的#using声明。出于某种原因,在项目参考 UI 中无法执行此操作。
回答by Vadim
You can use AssemblyHelper toolthat will generate InternalsVisibleTo syntax for you. Here's the link to the latest version. Just note that it only works for strongly-named assemblies.
您可以使用AssemblyHelper 工具为您生成 InternalsVisibleTo 语法。这是最新版本的链接。请注意,它仅适用于强命名程序集。
回答by Vadim
Here's a macro I use to quickly generate this attribute. Its a bit hacky, but it works. On my machine. When the latest signed binary is in /bin/debug. Etc equivocation etc. Anyhow, you can see how it gets the key, so that'll give you a hint. Fix/improve as your time permits.
这是我用来快速生成此属性的宏。它有点hacky,但它有效。在我的机器上。当最新的签名二进制文件在/bin/debug. 等等模棱两可等等。无论如何,你可以看到它是如何获得密钥的,这样会给你一个提示。在时间允许的情况下修复/改进。
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
回答by Ash
You need to use the /out: compiler switch when compiling the friend assembly (the assembly that does not contain the InternalsVisibleTo attribute).
编译友元程序集(不包含 InternalsVisibleTo 属性的程序集)时,您需要使用 /out: 编译器开关。
The compiler needs to know the name of the assembly being compiled in order to determine if the resulting assembly should be considered a friend assembly.
编译器需要知道正在编译的程序集的名称,以确定生成的程序集是否应被视为友元程序集。
回答by Alex J
In addition to all of the above, when everything seems to be correct, but the friend assembly stubbornly refuses to see any internals, reloading the solution or restarting Visual Studiocan solve the problem.
除了以上所有情况,当一切似乎都正确,但朋友程序集固执地拒绝查看任何内部结构时,重新加载解决方案或重新启动 Visual Studio可以解决问题。
回答by Jochen
In my case using VS.Net 2015, I needed to sign BOTHassemblies (if at least 1 assembly shall be signed or you want to reference on the public key of your assembly).
在我使用 VS.Net 2015 的情况下,我需要对两个程序集进行签名(如果至少要签名 1 个程序集,或者您想引用程序集的公钥)。
My project didn't use signing at all. So I started adding a sign key to my test library and useing the InternalsVisibleTo-Attribute at my project's base library. But VS.Net always explained it couldn't access the friend methods.
我的项目根本没有使用签名。所以我开始向我的测试库添加一个签名密钥,并在我的项目的基础库中使用 InternalsVisibleTo-Attribute。但是 VS.Net 总是解释它无法访问朋友方法。
When I started to sign the base library (it can be the same or another sign key - as long as you do sign the base library), VS.Net was immediately able to work as expected.
当我开始对基本库进行签名时(它可以是相同的或另一个签名密钥 - 只要您对基本库进行签名),VS.Net 立即能够按预期工作。
回答by Tatiana Racheva
Another possibility that may be tricky to track down, depending on how your code is written.
另一种可能难以追踪的可能性,这取决于您的代码是如何编写的。
- You're invoking an internal method defined in X from another assembly Y
- The method signature uses internal types defined in Z
- You then have to add [InternalsVisibleTo] in X AND in Z
- 您正在从另一个程序集 Y 调用 X 中定义的内部方法
- 方法签名使用 Z 中定义的内部类型
- 然后你必须在 X 和 Z 中添加 [InternalsVisibleTo]
For example:
例如:
// In X
internal static class XType
{
internal static ZType GetZ() { ... }
}
// In Y:
object someUntypedValue = XType.GetZ();
// In Z:
internal class ZType { ... }
If you have it written like above, where you're not referring to ZType directly in Y, after having added Y as a friend of X, you may be mystified why your code still doesn't compile.
如果你像上面那样写,你没有在 Y 中直接引用 ZType,在将 Y 添加为 X 的朋友之后,你可能会奇怪为什么你的代码仍然不能编译。
The compilation error could definitely be more helpful in this case.
在这种情况下,编译错误肯定会更有帮助。

