C#程序集Assembly学习随笔(第一版)_AX
①什么是程序集?
可以把程序集简单理解为你的.NET项目在编译后生成的*.exe或*.dll文件.
嗯,这个确实简单了些,但我是这么理解的.详细:
http://blog.csdn.net/sws8327/archive/2006/09/21/1244642.aspx
②程序集和命名空间的区别?
一个程序集可以跨越n个命名空间,一个命名空间也可以包含n个程序集.(估计你该晕了)
如果说命名空间是类库的逻辑组织形式,那么程序集就是类库的物理组织形式。只有同时指定类型所在的命名空间及实现该类型的程序集,才能完全限定该类型。(摘抄自《精通.NET核心技术--原来与架构》 电子工业出版社)
也就是说,你要创建一个类的实例,必须知道该类的 命名空间(这个一般都知道)+程序集(这个很容易被我们忽略,因为一般我们不需要引用外部的程序集,如果你用C#做过Excel文件的导入导出,就会知道必须添加一个Excel相关的程序集引用)
③怎样通过命令行创建程序集?
我对命令行向来反感,如果你想知道,look here:
http://www.cnblogs.com/3echo/archive/2006/02/14/330579.html
④我怎么把项目和程序集联系起来理解?
一个项目对应一个程序集.项目名与程序集名相同(03版,05版乱七八糟,随机生成的程序集名).
一般的我们每创建一个.NET项目(ASP.NET(VS2005里没有),WinForm,类库,控制台等),IDE都会自动生成一个AssemblyInfo.cs的文件,打开看看(03版)
汗,,[assembly: AssemblyTitle("")],,,,竟然程序集名是空的....不过你从该项目的文件夹里确实能翻出与项目名相同的.dll文件.估计如果你不在这条语句里赋值,IDE默认生成的程序集与项目名相同.大胆用吧.(可是,我不知道怎么用程序集?敬请期待下一篇:C#反射Reflection学习随笔_AX)
⑤自知,我的解决方案(包含0~n个项目)用到了什么程序集?
⑥我们苦苦寻觅的Assembly里面到底是什么东西?有什么值得我们去苦苦探究的?
其实在上面的AssemblyInfo.cs代码中,我们已经看出来一些东西,它里面包含该Assembly的名称/产品/描述/拷贝权..(鬼才关心)和版本号(这个很重要,但我觉得还是没什么太大的用处,是dll Hell 的克星,顺带说一句,同一Assembly名称的不同版本号的Assembly可同时运行),还有一个密钥的概念,共享程序集和部署用的,看了半天没看明白,就不误人子弟了.
那Assembly的主要用处是 :
ⅰ与反射Reflection结合起来用,动态创建你所需要的类!!
ⅱ与反射Reflection结合起来用,获得Assemble里类的信息
(据可靠的小道消息说Assembly里存的是一张包含元数据类名什么的表)
ⅲ使用别人已封装好的类.
可以把程序集简单理解为你的.NET项目在编译后生成的*.exe或*.dll文件.
嗯,这个确实简单了些,但我是这么理解的.详细:
http://blog.csdn.net/sws8327/archive/2006/09/21/1244642.aspx
②程序集和命名空间的区别?
一个程序集可以跨越n个命名空间,一个命名空间也可以包含n个程序集.(估计你该晕了)
如果说命名空间是类库的逻辑组织形式,那么程序集就是类库的物理组织形式。只有同时指定类型所在的命名空间及实现该类型的程序集,才能完全限定该类型。(摘抄自《精通.NET核心技术--原来与架构》 电子工业出版社)
也就是说,你要创建一个类的实例,必须知道该类的 命名空间(这个一般都知道)+程序集(这个很容易被我们忽略,因为一般我们不需要引用外部的程序集,如果你用C#做过Excel文件的导入导出,就会知道必须添加一个Excel相关的程序集引用)
③怎样通过命令行创建程序集?
我对命令行向来反感,如果你想知道,look here:
http://www.cnblogs.com/3echo/archive/2006/02/14/330579.html
④我怎么把项目和程序集联系起来理解?
一个项目对应一个程序集.项目名与程序集名相同(03版,05版乱七八糟,随机生成的程序集名).
一般的我们每创建一个.NET项目(ASP.NET(VS2005里没有),WinForm,类库,控制台等),IDE都会自动生成一个AssemblyInfo.cs的文件,打开看看(03版)
1
using System.Reflection;
2 using System.Runtime.CompilerServices;
3
4 //
5 // 有关程序集的常规信息是通过下列
6 // 属性集控制的。更改这些属性值可修改与程序集
7 // 关联的信息。
8 //
9[assembly: AssemblyTitle("")]
10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("")]
13[assembly: AssemblyProduct("")]
14[assembly: AssemblyCopyright("")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18 //
19 // 程序集的版本信息由下列 4 个值组成:
20 //
21 // 主版本
22 // 次版本
23 // 内部版本号
24 // 修订号
25 //
26 // 您可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,方法是按
27 // 如下所示使用 '*':
28
29[assembly: AssemblyVersion("1.0.*")]
30
31 //
32 // 要对程序集进行签名,必须指定要使用的密钥。有关程序集签名的更多信息,请参考
33 // Microsoft .NET Framework 文档。
34 //
35 // 使用下面的属性控制用于签名的密钥。
36 //
37 // 注意:
38 // (*) 如果未指定密钥,则程序集不会被签名。
39 // (*) KeyName 是指已经安装在计算机上的
40 // 加密服务提供程序(CSP)中的密钥。KeyFile 是指包含
41 // 密钥的文件。
42 // (*) 如果 KeyFile 和 KeyName 值都已指定,则
43 // 发生下列处理:
44 // (1) 如果在 CSP 中可以找到 KeyName,则使用该密钥。
45 // (2) 如果 KeyName 不存在而 KeyFile 存在,则
46 // KeyFile 中的密钥安装到 CSP 中并且使用该密钥。
47 // (*) 要创建 KeyFile,可以使用 sn.exe(强名称)实用工具。
48 // 在指定 KeyFile 时,KeyFile 的位置应该相对于
49 // 项目输出目录,即
50 // %Project Directory%\obj\<configuration>。例如,如果 KeyFile 位于
51 // 该项目目录,应将 AssemblyKeyFile
52 // 属性指定为 [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
53 // (*) “延迟签名”是一个高级选项 - 有关它的更多信息,请参阅 Microsoft .NET Framework
54 // 文档。
55 //
56[assembly: AssemblyDelaySign( false)]
57[assembly: AssemblyKeyFile("")]
58[assembly: AssemblyKeyName("")]
59
2 using System.Runtime.CompilerServices;
3
4 //
5 // 有关程序集的常规信息是通过下列
6 // 属性集控制的。更改这些属性值可修改与程序集
7 // 关联的信息。
8 //
9[assembly: AssemblyTitle("")]
10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("")]
13[assembly: AssemblyProduct("")]
14[assembly: AssemblyCopyright("")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18 //
19 // 程序集的版本信息由下列 4 个值组成:
20 //
21 // 主版本
22 // 次版本
23 // 内部版本号
24 // 修订号
25 //
26 // 您可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值,方法是按
27 // 如下所示使用 '*':
28
29[assembly: AssemblyVersion("1.0.*")]
30
31 //
32 // 要对程序集进行签名,必须指定要使用的密钥。有关程序集签名的更多信息,请参考
33 // Microsoft .NET Framework 文档。
34 //
35 // 使用下面的属性控制用于签名的密钥。
36 //
37 // 注意:
38 // (*) 如果未指定密钥,则程序集不会被签名。
39 // (*) KeyName 是指已经安装在计算机上的
40 // 加密服务提供程序(CSP)中的密钥。KeyFile 是指包含
41 // 密钥的文件。
42 // (*) 如果 KeyFile 和 KeyName 值都已指定,则
43 // 发生下列处理:
44 // (1) 如果在 CSP 中可以找到 KeyName,则使用该密钥。
45 // (2) 如果 KeyName 不存在而 KeyFile 存在,则
46 // KeyFile 中的密钥安装到 CSP 中并且使用该密钥。
47 // (*) 要创建 KeyFile,可以使用 sn.exe(强名称)实用工具。
48 // 在指定 KeyFile 时,KeyFile 的位置应该相对于
49 // 项目输出目录,即
50 // %Project Directory%\obj\<configuration>。例如,如果 KeyFile 位于
51 // 该项目目录,应将 AssemblyKeyFile
52 // 属性指定为 [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
53 // (*) “延迟签名”是一个高级选项 - 有关它的更多信息,请参阅 Microsoft .NET Framework
54 // 文档。
55 //
56[assembly: AssemblyDelaySign( false)]
57[assembly: AssemblyKeyFile("")]
58[assembly: AssemblyKeyName("")]
59
汗,,[assembly: AssemblyTitle("")],,,,竟然程序集名是空的....不过你从该项目的文件夹里确实能翻出与项目名相同的.dll文件.估计如果你不在这条语句里赋值,IDE默认生成的程序集与项目名相同.大胆用吧.(可是,我不知道怎么用程序集?敬请期待下一篇:C#反射Reflection学习随笔_AX)
⑤自知,我的解决方案(包含0~n个项目)用到了什么程序集?
//
遍历访问当前应用程序域的程序集Assemble
foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
{
//反射当前程序集的信息
Response.Write("Assembly:"+assem.FullName+"<br>");
}
foreach (Assembly assem in AppDomain.CurrentDomain.GetAssemblies())
{
//反射当前程序集的信息
Response.Write("Assembly:"+assem.FullName+"<br>");
}
⑥我们苦苦寻觅的Assembly里面到底是什么东西?有什么值得我们去苦苦探究的?
其实在上面的AssemblyInfo.cs代码中,我们已经看出来一些东西,它里面包含该Assembly的名称/产品/描述/拷贝权..(鬼才关心)和版本号(这个很重要,但我觉得还是没什么太大的用处,是dll Hell 的克星,顺带说一句,同一Assembly名称的不同版本号的Assembly可同时运行),还有一个密钥的概念,共享程序集和部署用的,看了半天没看明白,就不误人子弟了.
那Assembly的主要用处是 :
ⅰ与反射Reflection结合起来用,动态创建你所需要的类!!
ⅱ与反射Reflection结合起来用,获得Assemble里类的信息
(据可靠的小道消息说Assembly里存的是一张包含元数据类名什么的表)
ⅲ使用别人已封装好的类.
程序集是任何 .NET Framework 应用程序的基本构造块。例如,在生成简单的 C# 应用程序时,Visual Studio 创建一个单个可移植可执行 (PE) 文件形式的程序集,明确地说就是一个 EXE 或 DLL。
程序集概述
程序集具有以下特点:
程序集作为 .exe 或 .dll 文件实现。
通过将程序集放在全局程序集缓存中,可在多个应用程序之间共享程序集。
要将程序集放在全局程序集缓存中,必须对程序集进行强命名。
程序集仅在需要时才加载到内存中。
可以使用反射来以编程方式获取关于程序集的信息。
如果加载程序集的目的只是对其进行检查,应使用诸如 ReflectionOnlyLoadFrom 的方法。
可以在单个应用程序中使用相同程序集的两个版本。
程序集概述
程序集具有以下特点:
程序集作为 .exe 或 .dll 文件实现。
通过将程序集放在全局程序集缓存中,可在多个应用程序之间共享程序集。
要将程序集放在全局程序集缓存中,必须对程序集进行强命名。
程序集仅在需要时才加载到内存中。
可以使用反射来以编程方式获取关于程序集的信息。
如果加载程序集的目的只是对其进行检查,应使用诸如 ReflectionOnlyLoadFrom 的方法。
可以在单个应用程序中使用相同程序集的两个版本。
Assembly能干什么?
我们可以通过Assembly的信息来获取程序的类,实例等编程需要用到的信息。
一个简单的演示实例:
1.建立一个Console工程名为:NamespaceRef
2.写入如下代码:
1
using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Reflection;
5
6 namespace NamespaceRef
7 {
8 class Program
9 {
10 static void Main( string[] args)
11 {
12 Country cy;
13 String assemblyName = @"NamespaceRef";
14 string strongClassName = @"NamespaceRef.China";
15 // 注意:这里类名必须为强类名
16 // assemblyName可以通过工程的AssemblyInfo.cs中找到
17 cy = (Country)Assembly.Load(assemblyName).CreateInstance(strongClassName);
18 Console.WriteLine(cy.name);
19 Console.ReadKey();
20 }
21 }
22
23 class Country
24 {
25 public string name;
26 }
27
28 class Chinese : Country
29 {
30 public Chinese()
31 {
32 name = "你好";
33 }
34 }
35
36 class America : Country
37 {
38 public America()
39 {
40 name = "Hello";
41 }
42 }
43 }
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Reflection;
5
6 namespace NamespaceRef
7 {
8 class Program
9 {
10 static void Main( string[] args)
11 {
12 Country cy;
13 String assemblyName = @"NamespaceRef";
14 string strongClassName = @"NamespaceRef.China";
15 // 注意:这里类名必须为强类名
16 // assemblyName可以通过工程的AssemblyInfo.cs中找到
17 cy = (Country)Assembly.Load(assemblyName).CreateInstance(strongClassName);
18 Console.WriteLine(cy.name);
19 Console.ReadKey();
20 }
21 }
22
23 class Country
24 {
25 public string name;
26 }
27
28 class Chinese : Country
29 {
30 public Chinese()
31 {
32 name = "你好";
33 }
34 }
35
36 class America : Country
37 {
38 public America()
39 {
40 name = "Hello";
41 }
42 }
43 }
由于Assembly的存在给我们在实现设计模式上有了一个更好的选择。
我们在开发的时候有时候会遇到这样的一个问题,根据对应的名称来创建指定的对象。如:给出chinese就要创建一个chinese对象,以前我们只能这样来写代码:
1
if (strongClassName == "China")
2 cy = new China();
3 else if (strongClassName == "America")
4 cy = new America();
那么如果我们有很长的一系列对象要创建,这样的代码维护起来是很困难的,而且也不容易阅读。现在我们可以通过在外部文件定义类的程序集名称和类的强名称来获得这样一个实例,即易于理解,又增强了扩展性还不用修改代码。
2 cy = new China();
3 else if (strongClassName == "America")
4 cy = new America();
cy = (Country)Assembly.Load(assemblyName).CreateInstance(strongClassName);
结论
Assembly类有很多的方法和属性,它和Type一样有很多功能用于名称与方法和属性之间的转化。深入理解这两个类,你就可以清晰通用语言层是如何工作。