InternalsVisibleToAttribute 类

定义

指定通常仅在当前程序集内可见的类型对指定的程序集可见。

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;
      else
         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
      Else
         Return dir
      End If   
   End Function
End Class

如果以下示例编译为名为Friend1强名称的程序集,则Example.MainFriend1该方法可以成功调用FileUtilities.AppendDirectorySeparator该方法,尽管该方法在程序集内部Assembly1。 如果要从命令行在 C# 中编译,则必须使用 /out 编译器开关来确保编译器绑定到外部引用时,友元程序集的名称可用。

//
// 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 = FileUtilities1.AppendDirectorySeparator(dir)
        Console.WriteLine(dir)
   End Sub
End Module
' The example displays the following output:
'       C:\Program Files\

未签名的程序集

以下示例使用 InternalsVisibleToAttribute 特性使 internal 未签名程序集的成员对另一个未签名程序集可见。 该特性可确保 命名 程序集中的方法对名为 的程序集中的代码可见。 下面是 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 System;

public class Example1
{
   public static void Main()
   {
      String s = "The Sign of the Four";
      //Console.WriteLine(Utilities.StringUtilities.StringLib.IsFirstLetterUpperCase(s));
   }
}
Module Example1
    Public Sub Main()
        Dim s As String = "The Sign of the Four"
        ' Console.WriteLine(Utilities.StringUtilities.StringLib.IsFirstLetterUpperCase(s))
    End Sub
End Module

注解

InternalsVisibleToAttribute 特性指定通常仅在当前程序集内可见的类型对指定的程序集可见。

通常,在 C# 中具有internal作用域的类型和成员或在 Visual Basic 中具有Friend作用域的类型和成员,仅在定义它们的程序集中可见。 作用域为 protected internal 的类型和成员(在 Visual Basic 中为作用域 Protected Friend)仅对其所在程序集可见,或对从其包含类派生的类型可见。 具有 private protected 范围(Private Protected范围(Visual Basic)的类型和成员在包含类或从当前程序集中的包含类派生的类型中可见。

InternalsVisibleToAttribute 属性使得这些类型和成员也对指定程序集中的类型可见,这被称为友元程序集。 这仅适用于 internalFriend 在 Visual Basic 中)、 protected internalProtected Friend 在 Visual Basic 中)和 private protectedPrivate Protected 在 Visual Basic 中)成员,但不适用于 private 这些成员。

注释

对于 private protectedPrivate Protected 在 Visual Basic 中)成员,该 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 构造函数。

不要在参数中包含CultureInfoVersionProcessorArchitecture字段的值,Visual Basic、C#和C++编译器将此视为编译器错误。 如果使用的编译器不将此视为错误(如 IL 汇编程序 (ILAsm.exe))并且程序集具有强名称,那么首次指定的友元程序集访问包含 MethodAccessException 属性的程序集时,将引发 InternalsVisibleToAttribute 异常。

有关如何使用此属性的详细信息,请参阅 Friend 程序集C++友元程序集

获取完整的公钥

可以使用 强名称工具(Sn.exe) 从强名称密钥(.snk)文件中检索完整的公钥。 为此,请执行以下步骤:

  1. 将公钥从强命名密钥文件提取到单独的文件中:

    Sn -p <snk_file> <outfile>

  2. 向控制台显示完整的公钥:

    Sn -tp <outfile>

  3. 将完整的公钥值复制并粘贴到源代码中。

使用 C# 编译友元程序集

如果使用 C# 编译器编译友元程序集,则必须使用 /out 编译器选项显式指定输出文件的名称(.exe 或 .dll)。 这是必需的,因为编译器尚未生成它在绑定到外部引用时正在生成的程序集的名称。 对于 Visual Basic 编译器, /out 编译器选项是可选的,在使用 F# 编译器编译友元程序集时,不应使用相应的 -out-o 编译器选项。

使用 C++ 编译友元程序集

在 C++ 中,为了使由 InternalsVisibleToAttribute 属性启用的内部成员能被友元程序集访问,必须在 C++ 指令中使用 as_friend 属性。 有关详细信息,请参阅友元程序集(C++)。

构造函数

名称 说明
InternalsVisibleToAttribute(String)

使用指定的友元程序集的名称初始化类的新实例 InternalsVisibleToAttribute

属性

名称 说明
AllInternalsVisible

此属性未实现。

AssemblyName

获取使用关键字标记 internal 的所有类型和类型成员的友元程序集的名称。

TypeId

在派生类中实现时,获取此 Attribute的唯一标识符。

(继承自 Attribute)

方法

名称 说明
Equals(Object)

返回一个值,该值指示此实例是否等于指定对象。

(继承自 Attribute)
GetHashCode()

返回此实例的哈希代码。

(继承自 Attribute)
GetType()

获取当前实例的 Type

(继承自 Object)
IsDefaultAttribute()

在派生类中重写时,指示此实例的值是否为派生类的默认值。

(继承自 Attribute)
Match(Object)

在派生类中重写时,返回一个值,该值指示此实例是否等于指定对象。

(继承自 Attribute)
MemberwiseClone()

创建当前 Object的浅表副本。

(继承自 Object)
ToString()

返回一个表示当前对象的字符串。

(继承自 Object)

显式接口实现

名称 说明
_Attribute.GetIDsOfNames(Guid, IntPtr, UInt32, UInt32, IntPtr)

将一组名称映射为对应的一组调度标识符。

(继承自 Attribute)
_Attribute.GetTypeInfo(UInt32, UInt32, IntPtr)

检索对象的类型信息,该信息可用于获取接口的类型信息。

(继承自 Attribute)
_Attribute.GetTypeInfoCount(UInt32)

检索对象提供的类型信息接口的数量(0 或 1)。

(继承自 Attribute)
_Attribute.Invoke(UInt32, Guid, UInt32, Int16, IntPtr, IntPtr, IntPtr, IntPtr)

提供对对象公开的属性和方法的访问。

(继承自 Attribute)

适用于