友元程序集(C# 编程指南)

更新:2007 年 11 月

可以从一个程序集访问另一个程序集中的内部类型或内部成员。

备注

友元程序集功能用于访问内部成员;私有类型和私有成员仍然不可访问。

若要使程序集(程序集 B)能够访问另一个程序集(程序集 A)的内部类型和成员,应使用程序集 A 中的 InternalsVisibleToAttribute 属性。

说明:

在对将要访问另一个程序集(程序集 A)的内部类型或内部成员的程序集(程序集 B)进行编译时,必须用 /out 编译器选项显式指定输出文件的名称(.exe 或 .dll)(有关更多信息,请参见 /out)。这是必需的,因为当编译器将生成的程序集绑定到外部引用时,尚未为该程序集生成名称。

StrongNameIdentityPermission 类还提供共享类型的功能,其与友元程序集的区别如下:

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

  • 如果希望程序集 B 能够共享程序集 A 中的数百个类型,则必须使用 StrongNameIdentityPermission 修饰所有这些类型;而使用友元程序集时只需声明一次友元关系。

  • 使用 StrongNameIdentityPermission 时,想要共享的类型必须声明为公共类型。使用友元程序集时,会将共享类型声明为内部类型。

  • 有关如何生成可访问程序集中的非公共类型的 .netmodule 的信息,请参见 /moduleassemblyname

示例

在此示例中,程序集使内部类型和内部成员对名为 called cs_friend_assemblies_2 的程序集可见。

// cs_friend_assemblies.cs
// compile with: /target:library
using System.Runtime.CompilerServices;
using System;

[assembly:InternalsVisibleTo("cs_friend_assemblies_2")]

// internal by default
class Class1 
{
    public void Test() 
    {
        Console.WriteLine("Class1.Test");
    }
}

// public type with internal member
public class Class2 
{
    internal void Test() 
    {
        Console.WriteLine("Class2.Test");
    }
}

在此示例中,程序集使用程序集 cs_friend_assemblies.dll 中的内部类型和内部成员。

注意,必须显式指定输出文件的名称 (/out:cs_friend_assemblies_2.exe)。

如果此程序集允许另一个程序集(程序集 C)访问它的内部类型和成员,则程序集 C 不会自动变成程序集 cs_friend_assemblies.dll 的友元。

// cs_friend_assemblies_2.cs
// compile with: /reference:cs_friend_assemblies.dll /out:cs_friend_assemblies_2.exe
public class M 
{
    static void Main() 
    {
        // access an internal type
        Class1 a = new Class1();
        a.Test();

        Class2 b = new Class2();
        // access an internal member of a public type
        b.Test();
    }
}

Class1.Test
Class2.Test

此示例演示了如何使内部类型和成员对具有强名称的程序集可用。

若要生成 keyfile 并显示公钥,请使用下面的 sn.exe 命令序列(有关更多信息,请参见强名称工具 (Sn.exe)):

  • sn -k friend_assemblies.snk // 生成强名称密钥

  • sn -p friend_assemblies.snk key.publickey // 将公钥从 key.snk 提取到 key.publickey 中

  • sn -tp key.publickey // 显示存储在文件 key.publickey 中的公钥

/keyfile 将 keyfile 传递到编译器。

// cs_friend_assemblies_3.cs
// compile with: /target:library /keyfile:friend_assemblies.snk
using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("cs_friend_assemblies_4, PublicKey=0024000004800000940000000602000000240000525341310004000001000100031d7b6f3abc16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b428bf6cd9086021a0b38b76bc340dc6ab27b65e4a593fa0e60689ac98dd71a12248ca025751d135df7b98c5f9d09172f7b62dabdd302b2a1ae688731ff3fc7a6ab9e8cf39fb73c60667e1b071ef7da5838dc009ae0119a9cbff2c581fc0f2d966b77114b2c4")]
class Class1 
{
    public void Test() 
    {
        System.Console.WriteLine("Class1.Test");
    }
}

此示例演示如何使用对具有强名称的程序集可用的内部类型和成员。

// cs_friend_assemblies_4.cs
// compile with: /keyfile:friend_assemblies.snk /reference:cs_friend_assemblies_3.dll /out:cs_friend_assemblies_4.exe
public class M 
{
    static void Main() 
    {
        Class1 a = new Class1();
        a.Test();
    }
}

Class1.Test

请参见

概念

C# 编程指南

参考

程序集和全局程序集缓存(C# 编程指南)