public ref class InternalsVisibleToAttribute sealed : Attribute
[System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)]
public sealed class InternalsVisibleToAttribute : Attribute
[<System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)>]
type InternalsVisibleToAttribute = class
inherit Attribute
Public NotInheritable Class InternalsVisibleToAttribute
Inherits Attribute
InternalsVisibleToAttribute
已签名程序集
以下示例使用
InternalsVisibleToAttribute
特性使已
internal
签名程序集中名为
AppendDirectorySeparator
的方法对另一个已签名程序集可见。 它定义一个
FileUtilities
包含内部
AppendDirectorySeparator
方法的类。 特性
InternalsVisibleToAttribute
应用于包含 类的
FileUtilities
程序集。 特性允许名为 的
Friend1
程序集访问此内部成员。
// The source code should be saved in a file named Example1.cs. It
// can be compiled at the command line as follows:
// csc /t:library /keyfile:<snkfilename> Assembly1.cs
// The public key of the Friend1 file should be changed to the full
// public key stored in your strong-named key file.
using System;
using System.IO;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Friend1, PublicKey=002400000480000094" +
"0000000602000000240000525341310004000" +
"001000100bf8c25fcd44838d87e245ab35bf7" +
"3ba2615707feea295709559b3de903fb95a93" +
"3d2729967c3184a97d7b84c7547cd87e435b5" +
"6bdf8621bcb62b59c00c88bd83aa62c4fcdd4" +
"712da72eec2533dc00f8529c3a0bbb4103282" +
"f0d894d5f34e9f0103c473dce9f4b457a5dee" +
"fd8f920d8681ed6dfcb0a81e96bd9b176525a" +
"26e0b3")]
public class FileUtilities
internal static string AppendDirectorySeparator(string dir)
if (! dir.Trim().EndsWith(Path.DirectorySeparatorChar.ToString()))
return dir.Trim() + Path.DirectorySeparatorChar;
return dir;
' The source code should be saved in a file named Example1.cs. It
' can be compiled at the command line as follows:
' vbc Assembly1.vb /t:library /keyfile:<snkfilename>
' The public key of the Friend1 file should be changed to the full
' public key stored in your strong-named key file.
Imports System.IO
Imports System.Runtime.CompilerServices
<Assembly:InternalsVisibleTo("Friend1, PublicKey=002400000480000094" + _
"0000000602000000240000525341310004000" + _
"001000100bf8c25fcd44838d87e245ab35bf7" + _
"3ba2615707feea295709559b3de903fb95a93" + _
"3d2729967c3184a97d7b84c7547cd87e435b5" + _
"6bdf8621bcb62b59c00c88bd83aa62c4fcdd4" + _
"712da72eec2533dc00f8529c3a0bbb4103282" + _
"f0d894d5f34e9f0103c473dce9f4b457a5dee" + _
"fd8f920d8681ed6dfcb0a81e96bd9b176525a" + _
"26e0b3")>
Public Class FileUtilities
Friend Shared Function AppendDirectorySeparator(dir As String) As String
If Not dir.Trim().EndsWith(Path.DirectorySeparatorChar) Then
Return dir.Trim() + Path.DirectorySeparatorChar
Return dir
End If
End Function
End Class
如果将以下示例编译为名为
Friend1
的强名称程序集,则
Example.Main
中的
Friend1
方法可以成功调用
FileUtilities.AppendDirectorySeparator
方法,尽管 该方法是程序集的内部
Assembly1
方法。 请注意,如果要从命令行使用 C# 进行编译,则必须使用
/out
编译器开关来确保在编译器绑定到外部引用时友元程序集的名称可用。
// The assembly that exposes its internal types to this assembly should be
// named Assembly1.dll.
// The public key of this assembly should correspond to the public key
// specified in the class constructor of the InternalsVisibleTo attribute in the
// Assembly1 assembly.
#using <Assembly1.dll> as_friend
using namespace System;
void main()
String^ dir = L"C:\\Program Files";
dir = FileUtilities::AppendDirectorySeparator(dir);
Console::WriteLine(dir);
// The example displays the following output:
// C:\Program Files\
// The source code should be saved in a file named Friend1.cs. It
// can be compiled at the command line as follows:
// csc /r:Assembly1.dll /keyfile:<snkfilename> /out:Friend1.dll Friend1.cs
// The public key of the Friend1 assembly should correspond to the public key
// specified in the class constructor of the InternalsVisibleTo attribute in the
// Assembly1 assembly.
using System;
public class Example
public static void Main()
string dir = @"C:\Program Files";
dir = FileUtilities.AppendDirectorySeparator(dir);
Console.WriteLine(dir);
// The example displays the following output:
// C:\Program Files\
' The source code should be saved in a file named Friend1.vb. It
' can be compiled at the command line as follows:
' vbc Friend1.vb /r:Assembly1.dll /keyfile:<snkfilename>
' The public key of the Friend1 assembly should correspond to the public key
' specified in the class constructor of the InternalsVisibleTo attribute in the
' Assembly1 assembly.
Module Example
Public Sub Main()
Dim dir As String = "C:\Program Files"
dir = FileUtilities.AppendDirectorySeparator(dir)
Console.WriteLine(dir)
End Sub
End Module
' The example displays the following output:
' C:\Program Files\
无符号程序集
下面的示例使用
InternalsVisibleToAttribute
特性使
internal
未签名程序集的成员对另一个未签名程序集可见。 特性可确保
internal
StringLib.IsFirstLetterUpperCase
名为 的程序集中的方法对名为
UtilityLib
Friend2
的程序集中的代码可见。 下面是UtilityLib.dll的源代码:
using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleToAttribute("Friend2")]
namespace Utilities.StringUtilities
public class StringLib
internal static bool IsFirstLetterUpperCase(String s)
string first = s.Substring(0, 1);
return first == first.ToUpper();
Imports System.Runtime.CompilerServices
<assembly: InternalsVisibleTo("Friend2")>
Namespace Utilities.StringUtilities
Public Class StringLib
Friend Shared Function IsFirstLetterUpperCase(s As String) As Boolean
Dim first As String = s.Substring(0, 1)
Return first = first.ToUpper()
End Function
End Class
End Namespace
以下示例提供程序集的
Friend2
源代码。 请注意,如果要从命令行使用 C# 进行编译,则必须使用
/out
编译器开关来确保在编译器绑定到外部引用时友元程序集的名称可用。
#using <UtilityLib.dll> as_friend
using namespace System;
using namespace Utilities::StringUtilities;
void main()
String^ s = "The Sign of the Four";
Console::WriteLine(StringLib::IsFirstLetterUpperCase(s));
using System;
using Utilities.StringUtilities;
public class Example
public static void Main()
String s = "The Sign of the Four";
Console.WriteLine(StringLib.IsFirstLetterUpperCase(s));
Imports Utilities.StringUtilities
Module Example
Public Sub Main()
Dim s As String = "The Sign of the Four"
Console.WriteLine(StringLib.IsFirstLetterUpperCase(s))
End Sub
End Module
通常,具有
internal
C# 范围
或
Friend
Visual Basic 中的作用域
的类型和成员仅在定义它们的程序集中可见。 在 Visual Basic) 中具有
protected internal
范围 (
Protected Friend
范围的类型和成员仅在其自己的程序集或从其包含类派生的类型中可见。 在 Visual Basic) 中具有范围 (
Private Protected
范围的类型和成员
private protected
在包含类或从当前程序集中的包含类派生的类型中可见
特性
InternalsVisibleToAttribute
使这些类型和成员也对指定程序集(称为友元程序集)中的类型可见。 这仅适用于
internal
Visual Basic)
Friend
中的 (、
protected internal
Visual Basic) 中的 (
Protected Friend
,以及
private protected
Visual Basic) 成员中的 (
Private Protected
,但不适用于
private
成员。
private protected
在 Visual Basic) 成员中 (
Private Protected
的情况下,
InternalsVisibleToAttribute
属性仅将可访问性扩展到从成员的
包含类
派生的类型。
特性在程序集级别应用。 这意味着它可以包含在源代码文件的开头,也可以包含在 Visual Studio 项目的 AssemblyInfo 文件中。 可以使用 属性指定可以访问当前程序集的内部类型和成员的单个友元程序集。 可以通过两种方式定义多个友元程序集。 它们可以显示为单个程序集级属性,如以下示例所示。
[assembly:InternalsVisibleTo("Friend1a")]
[assembly:InternalsVisibleTo("Friend1b")]
<assembly:InternalsVisibleTo("Friend1a")>
<assembly:InternalsVisibleTo("Friend1b")>
它们还可以显示单独的
InternalsVisibleToAttribute
标记,但只显示一
assembly
个关键字,如以下示例所示。
[assembly:InternalsVisibleTo("Friend2a"),
InternalsVisibleTo("Friend2b")]
<Assembly:InternalsVisibleTo("Friend2a"), _
Assembly:InternalsVisibleTo("Friend2b")>
友元程序集由
InternalsVisibleToAttribute
构造函数标识。 当前程序集和友元程序集都必须未签名,或者两个程序集都必须使用强名称进行签名。
如果这两个程序集都是无符号的,则
assemblyName
参数由友元程序集的名称组成,该友元程序集在没有目录路径或文件扩展名的情况下指定。
如果两个程序集都使用强名称进行签名,则构造函数的参数
InternalsVisibleToAttribute
必须包含不带其目录路径或文件扩展名的程序集的名称,以及完整的公钥 (,而不是其公钥令牌) 。 若要获取强名称程序集的完整公钥,请参阅本文后面的
获取完整公钥
部分。 有关将 与强名称程序集一起使用
InternalsVisibleToAttribute
的详细信息,请参阅
InternalsVisibleToAttribute
构造函数。
不要在 参数中包含 、
Version
或
ProcessorArchitecture
字段的值
CultureInfo
;Visual Basic、C# 和 C++ 编译器将此视为编译器错误。 如果使用的编译器不将其视为错误 (如
IL 汇编程序 (ILAsm.exe)
) ,并且程序集具有强名称,
MethodAccessException
则当指定的友元程序集首次访问包含
InternalsVisibleToAttribute
该特性的程序集时,将引发异常。
有关如何使用此属性的详细信息,请参阅
友元程序集
和
C++ 友元程序集
。
获取完整的公钥
可以使用
强名称工具 (Sn.exe)
从强名称密钥 (.snk) 文件中检索完整的公钥。 为此,请执行以下步骤:
将公钥从强命名密钥文件提取到单独的文件中:
Sn -p
snk_file
outfile
向控制台显示完整的公钥:
Sn -tp
outfile
将完整的公钥值复制并粘贴到源代码中。
使用 C 编译友元程序集#
如果使用 C# 编译器编译友元程序集,则必须使用
/out
编译器选项显式指定输出文件 (.exe 或.dll) 的名称。 这是必需的,因为编译器尚未为它在绑定到外部引用时而正在构建的程序集生成名称。
/out
编译器选项对于 Visual Basic 编译器是可选的,在使用 F# 编译器编译友元程序集时,不应使用相应的
-out
或
-o
编译器选项。
使用 C++ 编译友元程序集
在 C++ 中,为了使由 属性启用
InternalsVisibleToAttribute
的内部成员可供友元程序集访问,必须在
as_friend
C++ 指令中使用 属性。 有关详细信息,请参阅
友元程序集 (C++)
。