CLR via C#学习笔记-第六章-类型的可见性

6.2 类型的可见性

要定义文件范围的类型时,可将类型的可见性指定为public或internal。

public类型不仅对定义程序集中的所有代码可见,还对其他程序集中的代码可见。

internal类型则仅对定义程序集中的所有代码可见,对其他程序集中的代码不可见。

定义类型时不显式指定可见性,C#编译器会帮你指定为internal。

//public即可有本程序集也可由其他程序集的代码访问
public class ThisIsAPublicType{}
//internal,只可有本程序集的代码访问
internal class ThisisAnInternalType{}
//没有显式声明,默认为internal
class ThisIsAlsoAnInternalType{}

友元程序集

将工具类型定义为internal,同时仍然允许其他人访问这些类型。

CLR和C#通过友元程序集friend assembly 提供这方面的支持。

一个程序集的代码对另一个程序集中的内部类型进行单元测试时,友元程序集功能也能派上用场。

生成程序集时,可用System.Runtime.CompilerServices命名空间中的InternalsVisibleTo特性标明它认为是友元的其他程序集。

该特性获取标识友元程序集名称和公钥的字符串参数。

注意,当程序集认了友元之后,友元程序集就能访问该程序集中的所有internal类型,以及这些类型的internal成员。

下例展示一个程序集如何将两个强命名程序集“Wintellect”和“Microsoft”指定为友元程序集

using System;
using System.Runtime.CompilerServices;

//当前程序集中的internal类型可由以下两个程序集中的任何代码访问
[assembly:InernalsVisibleTo("Wintellect,PublicKey=12345678...90abcdef")]
[assembly:InernalsVisibleTo("Microsoft,PublicKey=b77a5c56...1934e089")]

internal sealed class SomeInternalType{}
internal sealed class AnotherInternalType{}

从友元程序集访问上述程序集的internal类型很容易。

例如,下面展示了公钥相符的友元程序集Wintellect如何访问上述程序集的internal类型SomeInternalType

internal sealed class Foo
{
    private static Object SomeMethod()
    {
        //这个Wintellect程序集能访问另一个程序集的internal类型
        //就好像那是public
        SomeInternalType sit=new SomeInternalType();
        return sit;
    }
}

由于程序集中的类型的internal成员能从友元程序集访问,

所以要慎重考虑类型成员的可访问性,以及要将哪些程序集声明为友元。

注意,C#编译器在边缘友元程序集(不含InternalsVisibleTo特性的程序集)时,要求使用编译开关/out:<file>。

使用这个编译开关的原因在于,编译器需要知道准备编译的程序集的名称,从而判断生成的程序集时不是友元程序集。

事实上,在代码结束编译之前,C#是不知道输出文件名的。

同样的如果使用C#编译器的/t:module开关来编译模块(而不是编译成程序集),而且该模块将成为某个友元程序集的一部分,

那么还需要使用C#编译器的/moduleassemblyname:<string>开关来编译该模块,他告诉编译器该模块将成为哪个程序集的一部分,

使编译器设置模块中的代码,使他们能访问另一个程序集中的internal类型。

猜你喜欢

转载自www.cnblogs.com/errornull/p/9748961.html
今日推荐