分享

40. C#

 kiki的号 2017-04-25

什么是元数据?


元数据时一种二进制信息,用于对存储在公共语言运行库可移植可执行文件(PE)或存储在内存中的程序进行描述。     

在模块和程序集中定义和引用的每个类型和成员都将在元数据中进行说明。

当执行代码时,运行库将元数据加载到内存中,并引用它来发现有关代码的类、成员、继承等信息。

元数据以非特定语言的方式描述在代码中定义的每一类型和成员。


元数据存储以下信息:

程序集的说明:

1、标示(名称、版本、区域、公钥)

2、导出的类型

3、该程序集所依赖的其他程序集

4、运行所需的安全权限

 

类型的说明:

1、名称、可见性、基类和实现的接口

2、成员(方法、字段、属性、事件、嵌套)

 

属性:

修饰类型和成员的其他说明性元素。

 许多人不明白微软为什么要引入程序集,因为程序集允许我们分离可重用类型的逻辑或物理表示。

 

1、什么是程序集

      程序集是自我描述的安装单元,由一个或多个文件组成,一个程序集可以使一个包含元数据的DLL或EXE,也可以由多个文件组成,例如资源文件、元数据、DLL和EXE。由.net编译生成的exe文件或dll文件就是程序集。程序集是.net框架应用程序的生成块,包含编译好的代码的逻辑单元,创建每一个项目文件都会产生一个程序集dll。

   

      程序集是一个或多个类型定义文件及资源文件的集合. 公共语言运行库(CLR)操作的是程序集。在大多数情况下,程序集只有一个文程件构成。

2、程序集的结构

    1)程序集清单   2)类型元数据 3)MSIL代码  4)资源

3、程序集清单

    程序集的一个重要部分是程序集清单,它是元数据的一部分,描述了程序集和引用它所需要的所有信息,并列出所有的依赖关系。

4、私有程序集和共享程序集

    程序集是可以共享的,也可以是私有的。

    私有程序集位于应用程序所在的目录下,或其子目录中。使用私有程序集时,不需要考虑与其他类的命名冲突或版本冲突问题。在构建过程中引用的程序集会复制到应用程序的目录下。私有程序集是构建程序集的一般方式,特别是应用程序和组件在同一个公司中建立时,就更是如此。

    在使用共享程序集时,必须遵循一些规则。程序集必须是唯一的,因此,必须有一个惟一的名称(成为强名)。该名称的一部分是一个强制的版本号。当组件由另一个开发商构建,而不是应用程序的开发商构建时,以及一个大应用程序分布在几个小项目中时,常常需要使用共享程序集。

 

5、查看程序集

    程序集可以使用命令行工具ildasm来查看,这是一个MSIL(编译形成的中间代码)反汇编工具。

除了ildasm之外,.NET Reflector是另一个用于分析程序集的强大工具。

 

6、构建程序集

    模块是一个没有程序集特性的DLL(所以它不是程序集,但可以在以后添加到程序集中)。模块的作用是什么?模块可以更快的启动程序集,因为并不是所有的类都在一个文件中,模块只在需要的时候加载。使用模块的另一个原因是,需要多种编程语言来创建一个程序集。

 

7、程序集的属性

    在创建一个Visual Studio项目时,会自动生成源文件AssemblyInfo.cs,这个文件在Solution Explorer的Properties中。这个文件用于配置程序集清单。

    assembly:前缀把属性标记为程序集的全局属性。用于程序集的全局属性与特定的语言元素无关,用于程序集属性的参数时命名空间System.Reflection/ System.Runtime.Compiler Services 和 System.Runtime.InteropServices中的类。

 

8、动态加载和创建程序集

    在开发期间,添加对程序集的引用,使之包含在程序集引用中,该程序集中的类型就可以用于编译器。可以使用类Assembly的静态方法Load().

9.  加载程序集方法

.Net中加载程序集方法有几种:


一、隐式加载
        没有被显式加载但被引用的程序集,CLR会按照全局程序集缓存(GAC)、工作目录(应用程序所在目录)以及私有路径目录的顺序来寻找并加载。

二、AppDomain.Load 方法
    将一个程序集加载到一个特定的程序域中,主要用来供非托管代码调用

三、Assembly.Load方法
    通过接受一个程序集标识来加载程序集。如果是强命名程序集,则标识包括程序集名称、版本、语言文化、以及公有密钥标记,Load方法将导致CLR按照隐式加载的策略寻找并加载程序集。弱命名程序集则只是一个不带文件扩展名的程序集的名称,CLR不会到GAC中查找,如果没有指定私有目录,则在工作目录查找,如Assembly.Load("Math")。其中私有目录的定义可以在配置文件中指定。如应用程序MyApp.exe的配置文件可以定义为MyApp.exe.config。内容:
    

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8" ?>
    <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <probing privatePath="App;App1;" />
          </assemblyBinding>
       </runtime>
    </configuration>

  

     其中App和App1是两个在工作目录下的目录,用probing定义,存放需要在这个目录下被加载的程序集。如果使用工作目录以外的目录下的程序集,则可以使用codeBase元素来定义,可以在MSDN上查找其属性内容。

四、Assembly.LoadFrom方法
    参数是包括程序集清单的文件的名称或路径,包括文件扩展名。如需要加载D:/App/math.dll,可以使用语句:
    Assembly a = Assembly.LoadFrom(@"D:/App/math.dll");
    a即是加载的程序集。
    但这种方法有缺点,在MSDN上有详细的描述,我自己遇到的一个问题是加载一个在非工作目录下的程序集后,在另一个程序集中使用这个程序集中的对象进行反序列化时失败。使用Assembly.Load方法或者将该程序集放在工作目录下后问题得以解决。

五、Assembly.LoadFile方法
    用来加载指定路径上的程序集文件的内容。使用 LoadFile 方法来加载和检查具有相同标识但位于不同路径中的程序集。与 LoadFrom 不同,LoadFile 不会将文件加载到 LoadFrom 上下文中,也不会使用加载路径解析依赖项。LoadFile 在这个受限制的方案中很有用,因为 LoadFrom 不能用于加载标识相同但路径不同的程序集;它只加载第一个这样的程序集。

六、Assembly.LoadWithPartialName方法
    使用部分名称从应用程序目录或从全局程序集缓存加载程序集。参数为程序集标识,其中包含程序集的名称(不带文件扩展名)。程序集的版本、语言文化及公用密钥标记为可选。该方法执行时CLR首先检查应用程序的XML配置文件来搜索qualifyAssembly元素,若存在则该元素应能告诉CLR如何将一个部分的程序集标识映射为完全限定的标识,CRL将根据通常规则来查找程序集。若该元素不存在,CRL将使用指定名称在应用程序的工作目录和私有路径目录中搜索。若仍未找到,则到GAC中查找。

七、传统VC动态库的调用
    通过 P/Invoke 调用Win32 DLL

    using System.Runtime.InteropServices;//这是用到DllImport时候要引入的程序集

    [DllImport("DBAccess.dll",CharSet=CharSet.Auto)]
    static extern ulong FindApp( bool bIsTrue );
    //声明外部的标准动态库,跟Win32API是一样的.


参考:
http://blog.csdn.net/helloguonan/article/details/5914270 

http://blog.csdn.net/helloguonan/article/details/5914205 

本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1655198

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多