• .NET本质论 第1卷: 公共语言运行库 (Don Box, Chris Sells 著)


    第1章 CLR是一个更好的COM

    第2章 组件

    第3章 类型基础 (已看)

    第4章 用类型编程 (已看)

    第5章 实例 (已看)

    第6章 方法 (已看)

    第7章 高级方法

    第8章 域 (已看)

    第9章 安全性

    第10章 CLR外部环境

    词汇

    第1章 CLR是一个更好的COM

      COM 回顾

      公共语言运行库

      编程模型的演进

      我们走到哪儿了 

    第2章 组件

      模块定义

    CLR程序存在模块(module)中. 一个CLR模块是一个字节流, 通常作为一个文件存储在本地的文件系统中或者Web服务器上

    CLR模块包含代码, 元数据资源

    • IMetaDataEmit 接口是低级的COM接口,可以用来由经典的C++编程生成模块元数据
    • System.Reflection.Emit 命名空间是高级的类库,用来由任何CLR友好的语言编程生成元数据和CIL
    • CodeDOM则工作在更高级的抽象层面上

      程序集定义

      程序集名字

      公钥和程序集

      CLR加载器

      将名字解析成位置

      我们走到哪儿了

    第3章 类型基础

      类型概述

    类型是CLR程序的生成块(building block)

    CLR类型(CLR type)是命名的可重用抽象体.CLR类型的描述存放在CLR模块的元数据中,该模块还包含使类型工作所需要的CIL或者本机代码.完全限定的CLR类型名包括三个部分: 程序集名字, 可选的命名空间前缀和类型名称

    CTS有三种基本类型的成员: 字段,方法和嵌套类型. 其他类型成员(例如: 属性, 事件)是以附加元数据的形式出现的方法

    默认情况下, 确切的内存布局是不透明的 

      类型和初始化

    一个类型最多只有一个类型初始化器(.cctor),它没有参数和返回值,也不能被直接调用.它们是被CLR作为类型初始化的一部分自动调用的.

    单个C#类型既可以有显式的类型初始化方法,又能有带初始化表达式的静态字段声明,这是合法的.当两者都存在时,作为结果的.cctor方法将以字段初始化开始(按照声明的顺序)

    类型初始化器实际运行的时机,CLR将灵活处理.类型初始化器总是保证在首次访问类型的静态字段之前执行

    当类型的实例每次被分配时,CLR将自动调用构造函数(constructor)(.ctor) 

      类型和接口

    接口是整合到类型系统中的类型归类

    从结构上来说,接口与其他类型的真正区别是,在类型的元数据上是否存在interface特性 

      类型和基类型

      我们走到哪儿了 

    第4章 用类型编程

      运行时的类型

    CLR的每个对象都以一个固定大小的对象头开始,对象头不能通过程序直接访问, 但它确实存在

    对象头有两个字段: 它的第一个字段是同步块(sync block)索引,你可以使用这个字段推迟该对象与附加资源的关联(例如, 锁, COM对象); 对象头的第二个字段是一个句柄(handle),它指向一个不透明的数据结构, 用于表示该对象的类型. 

    在CLR的当前实现中,对象引用总是指向对象头的类型句柄字段. 第一个用户自定义类型的字段总是sizeof(void*)字节, 不管对象引用指向哪里

    给定类型的每个实例在对象头中都会有同样的类型句柄值. 类型句柄(type handle)简而言之是指向一个非透明的,无正式文档说明的数据结构的指针.这个数据结构包含了类型的完整描述,以及一个指向类型元数据的内存表示的指针.

    CIL: isinst castclass

    JIT编译器: JIT_IsInstance JIT_ChkCast

    using System;
    
    public sealed class Util {
        public static void UseType() {
            // 获取类型对象
            Type type = typeof(AcmeCorp.LOB.Customer);
            // 获取底层的类型句柄
            RuntimeTypeHandle htype = type.TypeHandle;
            // 从该句柄还原类型对象
            Type t2 = Type.GetTypeFromHandle(htype);
            // 现在, t2和type引用相同的System.Type对象
        }
    }
    using System;
    using System.Reflection;
    
    public sealed class Util {
        public static void UseType() {
            // 加载程序集
            Assembly assm = Assembly.LoadFrom("C:\acme.dll");
            // 获取类型对象
            Type type = assm.GetType("AcmeCorp.LOB.Customer");
            // 获取底层的类型句柄
            RuntimeTypeHandle htype = type.TypeHandle;
            // 从该句柄还原类型对象
            Type t2 = Type.GetTypeFromHandle(htype);
            // 现在, t2和type引用相同的System.Type对象
        }
    }
    using System;
    
    public sealed class Util {
        public static void DumpTypes(object o) {
            // 获取该对象的类型
            Type type = o.GetType();
            // 列出该类型直接的或者间接的基类型
            for (Type c = type; c != null; c = c.BaseType) {
                Console.WriteLine(c.AssemblyQuaifiedName);
            }
            // 列出该类型显式的或者隐式的接口
            Type[] itfs = type.GetInterfaces();
            for (int i = 0; i < itfs.Length; i++) {
                Console.WriteLine(itfs[i].AssemblyQualifiedName);
            }
        }
    }

      用元数据编程

    using System;
    using System.Reflection;
    
    public sealed class Util {
        public static void DumpMembers(Type type) {
            // 获取类型的成员
            MemberInfo[] members = type.GetMembers();
    
            // 列出成员
            for (int i = 0; i < members.Length; i++) {
                Console.WriteLine("{0} {1}", members[i].MemberType, members[i].Name);
            }
        }
    }

      

    using System;
    using System.Reflection;
    
    public sealed class Util {
        public static void DumpMembers(Type type) {
            // 获取类型的成员
            BindingFlags f = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Nonpublic | BindingFlags.FlattenHierarchy;
            MemberInfo[] members = type.GetMembers(f);
            // 列出成员
            for(int i = 0; i < members.Length; i++) {
                Console.WriteLine("{0} {1} ", members[i].MemberType, members[i].Name);
            }
        }
    }
    View Code

      特殊的方法

      元数据和可扩展性

    [assembly: Red]
    [module: Green]
    [class: Blue]
    [Yellow]
    public sealed class Widget {
        [return: Cyan]
        [method: Magenta]
        [Black]
        public int Splat() { }
    }

    自定义特性的存在与否不影响CLR对类型的处理.相反地,自定义特性处于一种休眠状态,等待程序使用反射和其他元数据接口去读取它们

    namespace System.Reflection {
        // MemberInfo, ParameterInfo, Assembly和Module都支持该接口
        public interface ICustomAttributeProvider {
            // 测试类型attType的特性存在与否
            bool IsDefined(System.Type attType, bool inherited);
            // 返回与atttType兼容的所有特性
            object[] GetCustomAttributes(System.Type attType, bool inherited);
            // 返回l类型无关的所有特性
            object[] GetCustomAttributes(bool inherited);
        }
    }
    System.Reflection.ICustomAttributeProvider
    using System;
    using System.Reflection;
    
    public sealed class Utils {
        static void DisplayMethodStatus(Type type) {
            foreach (MethodInfo m in type.GetMethods()) {
                Console.Write("{0} : ", m.Name);
            }
    
            // 检测DocumentedAttribute特性
            if (m.IsDefined(typeof(DocumentedAttribute), true)) {
                Console.Write("Documented");
            } else {
                Console.Write("Undocumented");
            }
    
            // 检测TestedAttribute特性
            if (m.IsDefined(typeof(TestedAttribute), true)) {
                Console.WriteLine(" - OK");
            } else {
                Console.WriteLine(" - Broken");
            }
        }
    }
    检测自定义特性
    using System;
    using System.Reflection;
    
    public sealed class Utils {
        static void DisplayMethodStatus2(Type type) {
            Type attType = typeof(DocumentedAttribute);
            foreach(MethodInfo m in type.GetMethods()) {
                Console.Write("{0} : ", m.Name);
            }
    
            // 检测DocumentedAttribute特性
            if (!m.IsDefined(attType, true)) {
                Console.WriteLine("Undocumented");
                continue;
            }
    
            object[] atts= m.GetCustomAttributes(attType, true);
            DocumentedAttribute att = (DocumentedAttribute)atts[0];
    
            Console.WriteLine("{0} : {1} words [{2}]", att.Writer, att.WordCount, (attReviewed ?"ok": "hold" ));
        }
    }
    检查自定义特性的参数

      我们走到哪儿了

    第5章 实例

      对象和值的比较

    考虑到一致性,我们在这里将对象定义为: 被垃圾回收的(garage-collected, GC)对上的CLR类型的实例

    值类型的实例不是对象, 因为它们既不以对象头开始,也不会在GC堆上分配明显的实体

     

    定义新的值类型有两种方式, 一种是以System.ValueType为基类型的类型; 另一种是以System.Enum为基类型的类型

    C#编译器不允许ValueType用作基类型

    你不能给C#的struct指定显式的基类型, 即隐含的基类型总是 System.ValueType

      变量,参数和字段

    引用类型new->CIL newobj

    值类型new->initobj

     

    向方法传递参数是赋值的变体

    按引用传递参数(在C#中用ref或out修饰符标识)

      相等与同一

    一般来说, 如果两个对象是相同类型的实例, 并且其中一个对象的各个字段匹配另一个对象的字段值, 那么这两个对象就是相等的(equivalent).

    如果两个对象在内存中共享一个地址, 则它们便是同一的(identical)

    GetHashCode 的默认实现并不保证唯一性或一致性,因此, 不能在进行散列时用作唯一对象标识符. 派生类必须用返回唯一散列代码的实现重写GetHashCode 

      克隆

    MemberwiseClone 执行的是浅表副本(shallow copy), 这意味着它只是将原对象的每个字段的值拷贝到克隆体中. 如果字段是一个对象引用,那么, 拷贝的仅仅是这个引用, 而不是引用的对象

    深层副本(deep copy)是指递归拷贝其字段所引用的所有对象

     

      装箱

    将值类型的实例"克隆"到堆上, 这个过程被称为装箱(boxing), 只要当一个值类型的实例被赋给一个对象引用变量, 参数或字段时,这个过程就会发生

    using System;
    
    
    public interface IAdjustor {
        void Adjust();
    }
    
    public struct Size: IAdjustor {
        public int height;
        public int width;
    
        public void Adjust() {
            height += 2;
            width += 3;
        }
    }
    
    public class App {
        static void Main() {
            Size s = new Size();
    
            bool truth = s.height == 0 && s.width == 0;
            Console.WriteLine(truth);
    
            s.Adjust();
            truth = s.height == 2 && s.width == 3;
            Console.WriteLine(truth);
    
            IAdjustor itf = s;  // 装箱
            itf.Adjust();   // 操作装箱的副本
            truth = s.height == 2 && s.width == 3;
            Console.WriteLine(truth);
    
            s = (Size)itf;  // 取消装箱
            truth = s.height == 4 && s.width == 6;
            Console.WriteLine(truth);
    
        }
    }
    装箱

     

      数组

    CLR支持两种复合类型: 一种是其成员可以通过局部的唯一名称访问; 另一种是其成员没有被命名,而是通过位置被访问.

    数组是引用类型的实例, 这个引用类型是CLR基于数组的元素类型和数组的维数[也称为秩(rank)]合成的

     

     

     

      对象生存期

      终结

      我们走到哪儿了

    第6章 方法

      方法和JIT编译

    CLR只执行本机的机器码

    将CIL转换到本机的机器码有两种解决的方法. 默认的场景是推迟转换, 直到该组件被加载到内存中时 

      方法调用和类型

      接口,虚方法和抽象方法

      显式方法调用

      间接方法调用和委托

      异步方法调用

      方法终止

      我们走到哪儿了

    第7章 高级方法

      动机

      作为方法调用的消息

      堆栈和消息转化

      代理类型

      消息过程(回顾)

      对象和上下文

      上下文和截获

      我们走到哪儿了

    第8章 域

      执行范围和CLR

    像进程一样, AppDomain是一个所有权(ownership)的单元 AppDomain的资源包括被加载的模块, 程序集和类型. 只要AppDomain被加载, 这些资源就一直在内存中. 卸载AppDomain是唯一卸载模块或者程序集的途径. 卸载AppDomain也是回收类型静态字段所占内存的唯一方式

    CLR定义了一个类型System.Threading.Thread, 在AppDomain中表示为可调度的(schedulable)实体, System.Threading.Thread线程对象有时被引用为软线程(soft thread),原因是它的构造无法为底层操作系统所识别. 相比之下, OS线程被引用为硬线程(hard thread), 因为它们是由OS处理的

    CLR维护硬线程的线程本地存储区(thread local storage TLS)中的一些信息. 特别是, 你会发现硬线程的TLS引用当前AppDomain和软线程对象 

      用AppDomain编程

    using System.Security.Policy;
    
    namespace System {
        public sealed class AppDomain: MarshalByRefObject _AppDomain, System.Security.IEvidenceFactory {
            // 获得“当前"域
            public static AppDomain CurrentDomain { get; };
    
            // 获取/设置特定域的环境变量
            public object GetData(string name);
            public void SetData(string name, object value);
    
            // 获取加载到域中的所有程序集
            public Assembly] GetAssemblies()
    
            // 产生新的AppDomain
            public static AppDomain CreateDomain(
                string friendlyName,    // 调试器的名字
                Evidence secinfo,    // 用于建立堆栈顶层的权限集
                AppDomainSetup ldrinfo);    // 包含AppDomain初始化信息的对象
    
            // 卸载现存的AppDomain
            public static void Unload(AppDomain target);
    
            // 加载基于EXE的程序集和运行Main(同步)
            public int ExecuteAssembly(string assemblyFile, Evidence assemblySecurity, string[] argv);
    
            // 在目标AppDomain中执行方法
            public void DoCallBack(CrossAppDomainDelegatecb);
            
            // 为了清晰明了, 其他成员省略
        }
    }
    System.AppDomain(节选)

    ExecuteAssembly方法先将AppDomain转化为子域.如果指定的程序集调用AppDomain.CurrentDomain方法, 它将获取子AppDomain对象.如果指定的程序集使用与父程序相同的任何程序集,则子AppDomain将加载它自己独立的类型与模块拷贝,包括它自己的静态字段集合

    using System;'
    
    public class MyApp {
        public static int Main(string[] argv) {
            // 创建域
            AppDomain child = AppDomain.CreateDomain("childapp");
            // 执行 yourapp.exe
            int r = child.ExecuteAssembly("yourapp.exe", null, argv);
            // 卸载域
            AppDomain.Unload(child);
            // 返回结果
            return r;
        }
    }
    生成新的应用程序

    在AppDomain中还可以插入任意代码. AppDomain.DoCallBack方法允许你在一个类型上指定一个方法, 它将在外部域中执行. 这个指定方法必须是静态的,并且它的签名与CrossAppDomainDelegate签名匹配. 此外, 为了执行这段代码,将不得不加载外部AppDomain中的指定方法的类型,模块和程序集. 如果指定方法需要在AppDomain之间共享信息,那么,它可以在外部AppDomain上使用SetData和GetData方法

    using System;
    using System.Diagnostics;
    using System.Reflection;
    
    public class MyApp {
        // 一个简单的例程,它将被加载的程序集的数目保存为一个AppDomain属性
        public static void CallbackProc() {
            AppDomain current = AppDomain.CurrentDomain;
            Console.WriteLine(current.FriendlyName);
            current.SetData("XX_assmcount", current.GetAssemblies().Length);
    
            var assm = current.GetAssemblies();
    
            foreach(var item in assm) {
                Console.WriteLine(item.FullName);
            }
        }
    
        // 这个例程开始工作
        static int GetAssemblyCount(AppDomain target) {
            // 创建委托
            CrossAppDomainDelegate cb = new CrossAppDomainDelegate(CallbackProc);
            // 插入并执行代码
            target.DoCallBack(cb);
            // 提取这个属性
            return (int)target.GetData("XX_assmcount");
        }
    
        // 生成一个域并且插入代码
        static void Main() {
            AppDomain child = AppDomain.CreateDomain("childapp", null, null);
            
            Console.WriteLine(GetAssemblyCount(child));
            Console.WriteLine(AppDomain.CurrentDomain.GetAssemblies().Length);
    
            var assm = AppDomain.CurrentDomain.GetAssemblies();
    
            foreach (var item in assm) {
                Console.WriteLine(item.FullName);
            }
    
            AppDomain.Unload(child);
        }
    }
    在外部AppDomain中调用

      AppDomain事件

     

     

    using System;
    
    class BadApp {
        // 这个方法是我们的处理程序
        static void AppHurts(Object sender, UnhandledExceptionEventArgs args) {
            Exception offender = args.ExceptionObject as Exception;
            if (args.IsTerminating) {
                
                // CleanUpBeforeDying();       
            }
        }
    
        static void Main() {
            // 这将注册用于整个过程的处理程序
            AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppHurts);
    
    
            throw new Exception("Hello");
            // int x = 3 / 0; // 导致异常
        }
    }
    注册一个未处理异常的事件处理程序

      AppDomain和程序集解析器

    using System;
    
    public class Test1 {
        static void Main() {
            // 提取当前的域
            AppDomain here = AppDomain.CurrentDomain;
    
            // 提取基目录路径的3种不同的方式
            string dir1 = here.BaseDirectory;
            Console.WriteLine(dir1);
            string dir2 = here.SetupInformation.ApplicationBase;
            Console.WriteLine(dir2);
            string dir3 = (string)here.GetData("APPBASE");
            Console.WriteLine(dir3);
        }
    }
    访问AppDomain的属性

     

      AppDomain和代码管理

    using System;
    
    public class MyApp {
        // 重写SingleDomain的默认方式
        [LoaderOptimization(LoaderOptimization.MultiDomain)]
        public static void Main() {
            // 在这里生成域, 并开始工作
        }
    }
    设置托管的可执行代码LoaderOptimization

      AppDomain和对象(回顾)

    你可能想将某个AppDomain的对象引用迁移到另一个域中 而这个对象引用又是AppDomain相关的 答案就是封送(marshaling) 

    CLR将所有对象,值和对象引用的作用域定为特定的AppDomain. 当需要将引用或者值传给另一个AppDomain时,首先必须封送它

    System.Runtime.Remoting

    System.Runtime.Remoting.RemotingServices.Marshal/Unmashal

    using System;
    
    class App {
        static void Main() {
            // 创建域
            AppDomain child = AppDomain.CreateDomain("c", null);
            // 在新的域中创建对象
            Object proxy = child.CreateInstance("someassm", "Bob").Unwrap();
    
            // 向下类型转换, 并且调用
            Bob b = (Bob)proxy;
            b.f();
        }
    }
    View Code
    using System;
    
    class App {
        static void Main() {
            // 创建两个域
            AppDomain c1 = AppDomain.CreateDomain("c1", null);
            AppDomain c2 = AppDomain.CreateDomain("c2", null);
    
            // 在第一个域中创建对象
            Object handle = c1.CreateInstance("someassm", "Bob");
            // 在c2的属性中保存对象的句柄
            c2.SetData("HeresYourHandle", handle);
            // 运行某个程序
            c2.ExecuteAssembly("foo.exe", null, null);
        }
    }
    View Code

      我们走到哪儿了

    第9章 安全性

      组件和安全性

      证据

      策略

      权限

      实施

      我们走到哪儿了

    第10章 CLR外部环境

      内存

    基于CLR的程序按部就班地使用验证的指针. 这种指针被称为托管(managed)指针. C#和VB.NET编译器在方法参数声明为传引用时,就使用托管指针.不同于C风格指针,托管指针不支持算数运算. 托管指针是强类型的,其本身就是类型的实例. 例如,指向System.Int32的托管指针是 System.Int32&类型的实例.托管指针之所以称为"托管", 其最终原因是, 在堆压缩(heap compaction)过程中当被引用的对象被移动时, 垃圾回收器能够调整指针的值

    CLR也支持第二种风格的指针, 即类似C风格的指针. 这种风格的指针被称为"非托管(unmanaged)"指针. 这里使用形容词"非托管", 是因为垃圾回收器在堆压缩时将忽略非托管指针. 同托管指针一样, 非托管指针也是某个类型的实例. 例如, 指向System.Int32非托管指针是System.Int32*类型的实例

    为了编译使用非托管指针的C#程序,必须使用/unsafe或者/unsafe+命令行参数. 这个开关导致编译器发射请求SkipVerification权限的权限集. 这个开关也允许在程序的源代码中使用非托管指针

    C#不鼓励使用非托管指针, 为此, 它要求非托管指针的使用只出现在一个被声明为unsafe的作用域(scope)内(例如, 方法作用域, 类型作用域)

      执行模式

      非托管模块

      加载CLR

      作为COM组件的CLR

      我们走到哪儿了

    词汇

    .Net Framework: 用于编写基于CLR应用程序和XML Web Services的技术集

    .Net Framework SDK: 可以免费下载的软件开发包, 用于编写和调试基于CLR的应用程序和XML Web Services

    abnormal termination (异常终止): 由于没有处理抛出的异常, 方法只好仓促退出

    abstract type (抽象类型): 只用作基类型的那些类型, 并且不能被用作实例化对象或值

    AL.EXE: .Net Framework SDK中的程序集链接器

    AppDomain: 在CLR中执行的基本作用域

    aspect-oriented programming (AOP, 面向方面的编程): 这是一种编程技术. 它对于不同concern的代码进行分解, 经常基于out-of-band声明和代码注入等隐式地执行

    assembly (程序集): 作为部署单位的一个或者多个模块的集合

    assembly loader (程序集加载器): CLR中代码的核心部分, 它将程序集的模块映射到内存中

    assembly reference (程序集引用): 外部程序集的引用, 它通常出现在程序集清单(manifest)中

    assembly resolver (程序集解析器): CLR中代码的核心部分, 在调用程序集加载器加载程序集之前, 通过名字定位程序集

    CASPOL.EXE: .Net Framework SDK的工具之一, 用于查看和控制安全策略.

    CL.EXE: 随.Net Framework SDK一起发布的C++编译器

    Common Intermediate Language (CIL, 公共中间语言): CLI使用的架构无关(architecture-neutral)的指令集

    Common Language Infrastructure (CLI, 公共语言架构): 由ECMA批准的一组规范, 它描述了CLR的公开方面

    Common Language Runtime (CLR, 公共语言运行库): Microsoft用于Windows(尤其是Windows.NET Server, Windows XP, Windows 2000, Windows NT4.0 SP6a或者之后的版本, Windows 98和Windows ME) 的CLI实现

    Common Language Specification (CLS, 公共语言规范): CTS的子集, 所有与CLI兼容的编程语言都必须遵守它

    Common type system (CTS, 通用类型系统): 语言无关的(language-neutral)类型系统, 用于CLI元数据和指令

    Component Object Model (COM, 组件对象模型): 20世纪90年代兴起的组件技术, 用于将类型加到加载器和组件元数据中

    Constructor (构造函数): 由CLR自动调用的方法, 用于初始化一个类型新的实例. 构造函数在结构上只是方法, 其方法名总是.ctor

    Contract (约定): 描述组件之间交互关系的协议

    CORDBG.EXE: 同.NET Framework一起发布的命令行式的调试器

    CSC.EXE: 同.NET Framework一起发布的C#编译器

    DBGCLR.EXE: 同.NET Framework一起发布的界面友好的调试器

    delegate (委托): 委托是一个对象, 它的存在只是为了调用目标对象的特定方法

    event (事件): 一组命名的方法集, 是注册事件处理程序的汇集点

    event handler (事件处理程序): 与CLR事件一起注册的委托对象

    evidance (证据): 有关程序集来源的证据, 这是由程序集加载器进行收集的, 并且对于给定代码段, 决定其安全策略

    exception (异常): 在程序执行过程中, 用于标识异常状态的对象.

    exception handler (异常处理程序): 用于处理由运行时隐式发出的或者throw语句显式发出的异常的代码

    field (字段): 命名的, 类型化的存储单元, 它属于一个类型或模块

    finalization (终止): 终止是通知对象其底层内存将要被回收的活动

    FUSLOGVW.EXE: .NET Framework SDK的工具之一, 用于查看由程序集解析器编写的日志文件

    GACUTIL.EXE: .NET Framework SDK的工具之一, 用于管理下载缓存和程序集缓存

    garbage collection (垃圾回收): CLR对代码无所不知, 当它自动侦查到存在未使用的内存时, 就会进行资源的回收. 这种方式就是垃圾回收

    Global Assembly Cache (GAC, 全局程序集缓存): 一个安全的,系统范围的代码缓存, 用于永久安装共享组件

    hard thread (硬线程): 操作系统线程

    IEEXEC.EXE: 通过IE启动基于CLR应用程序时所使用的宿主程序

    ILASM.EXE: 同.NET Framework一起发布的CIL汇编器

    ILDASM.EXE: .NET Framework SDK的工具之一, 用于显示模块与程序集的元数据与代码

    Interface Definition Language (IDL, 接口定义语言): COM元数据的基于文本的格式

    JSC.EXE: 同.NET Framework 一起发布的JavaScript编译器

    loader (加载器): 用于定位和准备代码执行的代码部分

    metadata (元数据): 在本书的上下文中, 元数据是描述组件的信息

    method (方法): 命名的, 类型化的执行单元, 它属于一个类型或者模块

    Microsoft Transaction Server (MTS, Microsoft事务服务器): COM的扩展,使用了类似AOP的技术, 提供了基于服务器端的服务

    module (模块): 包含代码,资源和元数据的文件

    NGEN.EXE: .NET Framework SDK的工具之一, 用于管理预编译的本机映像(native image)的缓存

    normal termination (正常终止): 方法的正常执行, 当到最后一条语句时, 显式地或者隐式地返回

    permission (权限): 执行受保护操作或者访问受保护资源的权力

    Permission Set (权限集): 一个无序的权限集合

    primitive type (基本数据类型): 也就是值类型. 它的值是原子的, 并且是CLR 所预先知道的12种内部类型之一(System.Boolean, System.Char, System.Double, System.Single, System.SByte, System.Int16, System.Int32, System.Int64, System.Byte和System.UInt16, System.UInt32和System.UInt64)

    property (属性): 一组命名的方法集, 用于表示一个逻辑特性

    public key (公钥): 一个大的,加密的唯一值, 用于标识一个用户或者组织,在CLR中主要用于识别程序集的开发者

    public key token (公钥标记): 公钥的加密哈希(hash)值, 便于快速查询和比较公钥. 在CLR中主要用于降低完全限定的程序集引用的大小

    reference type (引用类型): 对于其变量引用的是对象(潜在为null),而不是值, 这样的变量类型称为引用类型. 所有不直接或者间接派生于System.ValueType的类型都是引用类型

    REGASM.EXE: .NET Framework SDK的工具之一, 用于将CLR程序集注册为COM组件

    REGSVCS.EXE: .NET Framework SDK的工具之一, 用于通过COM+目录管理器注册CLR程序集

    RESGEN.EXE: 同.NET Framework一起发布的资源编译器

    sealed type (密封类型): 不能用作基类型的类型

    security policy (安全策略): 基于证据, 将权限集授予代码的规则

    shadow copying (影响拷贝): 程序集解析器的特征之一. 它加载的是程序集的拷贝, 这样就避免从底层文件中获取读锁

    SN.EXE: .NET Framework SDK的工具之一, 用于管理公钥/私钥和程序集

    SOAPSUDS.EXE: .NET Framework SDK的工具之一, 用于将Web服务的基于WSDL元数据转换为基于CLR的元数据. 参见WSDL.EXE

    soft thread (软线程): System.Threading.Thread类型的CLR线程对象

    strong name (强名称): 包含公钥(通常是指组件开发者的公钥)的程序集名称

    termination handler (终止处理程序): 在离开受保护的指令范围之前,被保证运行的代码, 不管是否发生异常

    thread local storage (TLS, 线程本地存储): 特定线程专用的数据

    TLBEXP.EXE: .NET Framework SDK的工具之一, 用于将基于CLR的元数据转换为基于COM的元数据

    TLBIMP.EXE: .NET Framework SDK的工具之一, 用于将基于COM的元数据转换为基于CLR的元数据

    type (类型): 一个命名的抽象单元

    type initializer (类型初始化器): 由CLR自动调用的方法, 用于初始化类型. 类型初始化器在结构上是方法, 其名字总是为.cctor

    type library (TLB, 类型库): 基于COM元数据的二进制格式

    uniform resource identifier (URI, 统一资源标识符): 能够唯一标识资源的基于文本的名字. URI既是统一资源定位符(URL), 也是统一资源名字(URN)

    uniform resource locator (URL, 统一资源定位符): 包含定位提示的URI

    uniform resource name (URN, 统一资源名字): 位置独立的URI

    value type (值类型): 对于其变量是具体的实例, 而不是实例的引用, 这样的变量类型称为值类型. 所有的值类型都是直接或间接地由System.ValueType继承而来的

    VBC.EXE: 同.NET Framework 一起发布的Visual Basic.NET编译器

    version policy (版本策略): 确定组件间适用版本的规则集

    Visual Studio.NET: Microsoft面向CLR的开发环境

    WINCV.EXE: .NET Framework SDK的工具之一,用于浏览系统程序集的类型层次

    WSDL.EXE: .NET Framework SDK的工具之一, 用于将基于CLR的元数据转换为Web服务的基于WSDL的元数据. 参见SOAPSUDS.EXE

    XSD.EXE: .NET Framework SDK的工具之一, 用于实现基于XML模式的元数据与基于CLR的元数据之间的转换

  • 相关阅读:
    关于wepy小程序图片显示问题
    输入地址到页面显示发生了写什么?
    一次Debug过程的思考
    一次冗长繁琐的排错经历
    PHP内核探索之变量(7)- 不平凡的字符串
    PHP内核探索之变量(6)- 后续内核探索系列大纲备忘
    PHP内核探索之变量(5)- session的基本原理
    PHP内核探索之变量(4)- 数组操作
    PHP内核探索之变量(3)- hash table
    PHP内核探索之变量(2)-理解引用
  • 原文地址:https://www.cnblogs.com/revoid/p/6664443.html
Copyright © 2020-2023  润新知