友元程序集

友元程序集是可以访问其他程序集内部(C#)或Friend(Visual Basic)类型和成员的程序集。 如果将程序集属性添加到 AssemblyA 以将 AssemblyB 标识为友元程序集,则不再需要将 AssemblyA 中的类型和成员标记为公共,以便 AssemblyB 访问它们。 在以下方案中,这特别方便:

  • 在单元测试期间,当测试代码在单独的程序集上运行,但要求访问标记为 C# 中的 internal 或 Visual Basic 中的 Friend 的正在被测试的程序集中的成员时。

  • 当您开发一个类库,并且类库的添加内容包含在单独的程序集时,然而这些程序集需要访问现有程序集中的成员,这些成员在 C# 中用 internal 标记或在 Visual Basic 中用 Friend 标记。

注解

可以使用特性 InternalsVisibleToAttribute 来标识给定程序集的一个或多个友元程序集。 以下示例使用 InternalsVisibleToAttributeAssemblyA 中的属性,并将程序集 AssemblyB 指定为友元程序集。 这样,程序集 AssemblyB 可以访问程序集 AssemblyA 中所有在 C# 中用 internal 标记或在 Visual Basic 中用 Friend 标记的类型和成员。

注释

编译程序集(如 AssemblyB)以访问其他程序集(如 AssemblyA)的内部类型或内部成员时,必须使用 -out 编译器选项显式指定输出文件的名称(.exe.dll)。 这是必需的,因为编译器尚未生成它在绑定到外部引用时正在生成的程序集的名称。 有关详细信息,请参阅 OutputAssembly (C#)-out (Visual Basic)。

using System.Runtime.CompilerServices;
using System;

[assembly: InternalsVisibleTo("AssemblyB")]

// The class is internal by default.
class FriendClass
{
    public void Test()
    {
        Console.WriteLine("Sample Class");
    }
}

// Public class that has an internal method.
public class ClassWithFriendMethod
{
    internal void Test()
    {
        Console.WriteLine("Sample Method");
    }

}
Imports System.Runtime.CompilerServices
<Assembly: InternalsVisibleTo("AssemblyB")>

' Friend class.
Friend Class FriendClass
    Public Sub Test()
        Console.WriteLine("Sample Class")
    End Sub
End Class

' Public class with a Friend method.
Public Class ClassWithFriendMethod
    Friend Sub Test()
        Console.WriteLine("Sample Method")
    End Sub
End Class

只有显式指定为好友的程序集才能访问 internal (C#) 或 Friend (Visual Basic) 类型和成员。 例如,如果 AssemblyB程序集 A程序集 C 引用 AssemblyB 的友元,则程序集 C 无权访问internalFriend 中的 (C#) 或 (Visual Basic) 类型。

编译器对传递给 InternalsVisibleToAttribute 特性的友元程序集名称执行一些基本验证。 如果 程序集 AAssemblyB 声明为友元程序集,则验证规则如下所示:

  • 如果 程序集 A 具有强名称, 则 AssemblyB 也必须具有强名称。 传递给特性的友元程序集名称必须包含程序集名称和用于对 AssemblyB 进行签名的强名称密钥的公钥。

    传递到 InternalsVisibleToAttribute 属性的友元程序集名称不能是程序集 B 的强名称。 请勿包含程序集版本、区域性、体系结构或公钥令牌。

  • 如果 程序集 A 不是强名称,则友元程序集名称应仅包含程序集名称。 有关详细信息,请参阅如何:创建未签名的友元程序集

  • 如果 AssemblyB 具有强名称,则必须使用项目设置或命令行编译器选项为 /keyfile 指定强名称键。 有关详细信息,请参阅如何:创建已签名的友元程序集

StrongNameIdentityPermission 类还提供共享类型的功能,但存在以下差异:

  • StrongNameIdentityPermission 应用于单个类型,而友元程序集应用于整个程序集。

  • 如果要将 程序集 A 中的数百种类型共享给 AssemblyB,则必须为所有这些类型添加StrongNameIdentityPermission。 如果使用友元程序集,只需声明友元关系一次。

  • 如果使用 StrongNameIdentityPermission,需要共享的类型必须声明为公共类型。 如果使用友元程序集,则共享类型声明为 internal (C#) 或 Friend (Visual Basic)。

有关如何从模块文件(扩展名为 internal 的文件)访问程序集Friend(C#)或 (Visual Basic) 类型和方法的信息,请参阅 ModuleAssemblyName (C#)-moduleassemblyname (Visual Basic)。

另请参阅