C#OOP之十三 组件、程序集与反射

简介: C#OOP之十三 组件、程序集与反射

视频:https://edu.csdn.net/course/detail/27107

组件



组件技术是软件领域一项非常大的成就。组件技术像搭积木游戏一样,在搭积木时,我们知道并不是任何的两个积木都可以组合,能组合的积木之间必定存在可以衔接的接口,同时,已经搭好的积木可以作为一个整体的大积木,被用来与其他积木组合。


       在软件领域,这些“积木”模型有微软的COM,Sun的JavaBean、.Net的程序集等。


       组件可以提高子程序的重用性和灵活性,并便于子程序的发布。也可以节省开发时间,提高程序的可靠性。


       例如,Shapes类包含代表圆、三角形或其他图形的对象。它的方法可用于计算图形面积或执行图形的其他操作。许多程序都要使用Shape类,完成如下功能:加色/绘图程序、Visio/PPT/Word画图、建筑/施工设计、CAD、游戏及其他程序。


      如果把Shapes设计成组件,仅定义一次,被在多个程序重用性,岂不美哉?(注意:不是在多个程序中Ctrl+C、Ctrl+V该类,这就太代码工人了。)


       在.Net编程模型中,我们使用程序集来实现组件技术的使用。

 

程序集

 

对于.Net来讲,无论C#、VB、J#那种语言的应用程序编译的最终结果都是一个程序集。编译而成的程序集包括我们提到的Exe文件或DLL文件。.Net编译生成的Exe文件和常规我们见的二进制可执行文件(exe文件,比如说QQ.exe)是不一样的,它是由中间语言(IL)组成的可执行文件,必须由CLR来执行。


程序集具有以下特点:


·                程序集作为 .exe 或 .dll 文件实现。


·                通过将程序集放在全局程序集缓存中,可在多个应用程序之间共享程序集。


·                要将程序集包含在全局程序集缓存中,必须对程序集进行强命名。


·                程序集仅在需要时才加载到内存中。


·                可以使用反射以编程方式获取关于程序集的信

创建与使用程序集

 

第1步:建立控制台项目,给项目改名为“CalcShapes”,如下图:

 

 

 

第3步:查看解决方案,并修改Shapes类库项目中的“Class1.cs”名为“Circle.cs”

 

 

 

第4步:编写Circle类的代码:

 

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
namespace Shapes
{
   public classCircle
   {
        double radius;
       public doubleRadius
       {
            get{ return radius; }
            set{ radius = value; }
       }
       public Circle()
       {
            radius = 0;
       }
       public Circle(doublegivenRadius)
       {
            radius = givenRadius;
       }
       public doublegetArea()
       {
            returnSystem.Math.PI * (radius * radius);
       }
   }
}

第5步:在控制台程序使用Shapes项目中的程序集,在CalcShapes项目的“引用”上右键单击“添加引用”,然后弹出下面的对话框,选择“项目”选项卡,选择“Shapes”项目,然后点击“确定”按钮即可。

 

 

 

 

第6步:在控制台程序中编写代码,并查看运行效果;

 

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingShapes;  //1.引用命名空间;
namespaceCalcShapes
{
    class Program
   {
       static voidMain(string[]args)
       {
            Circlecircle1 = new Circle();
            circle1.Radius = 3.3;  //设置圆周率
            Console.WriteLine(circle1.getArea().ToString()); //现实圆面积
       }
   }
}

 

项目1:使用Winform来添加Shapes类引用

 

项目背景:针对我们已经写好的程序集文件,方便我们在以后在各种程序中使用,所以,我们应该从各个方面将该组件淋漓尽致使用的“压榨干净”。在上述基础上,添加新项目

解决方案:学习添加Winform项目

步骤1:添加Winform新项目到刚才的项目,如下图:

 

 

 

步骤4:编写代码:

 

usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
usingShapes; //1.引用命名空间
namespaceWinCalc
{
   public partialclassForm1 : Form
   {
       public Form1()
       {
            InitializeComponent();
       }
       private voidbutton1_Click(object sender,EventArgs e)
       {
            doubleradious = 0.0;
            Circlecircle1 = new Circle();
            circle1.Radius = Convert.ToDouble(radious);
            MessageBox.Show("圆的面积为:" +circle1.getArea().ToString());
       }
   }
}

步骤5:设置WinCalc为启动项目,如下图,然后运行(F5):

 

 

 

 

步骤6:出现运行界面,输入半径,如下图:

 

 

 

 

思考与扩充,在.Net中程序集组件引用的本质是多加几个类库项目,而是引用的其中的核心组件是什么?

请注意添加引用的本质是类库项目所对应的程序集文件,如Shapes\bin\DebugShapes.dll文件。

【扩充在VB下使用C#的dll文件】

1.      界面设计省略同C#

2.代买比较痛苦:  

PublicClass Form1
    Private Sub Button1_Click(ByVal sender AsSystem.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim circle As Shapes.Circle
        circle = New Shapes.Circle()
        circle.Radius = 3.3
        MessageBox.Show("VB圆面积" +circle.getArea().ToString())
    End Sub
End Class

2.      效果如下:

 

 

 

 

 

深入研究程序集

 

对于可执行的程序集来讲,包含五部分的信息:


n       PE32头


这是标准的Windows可执行文件头,它可以引导操作系统对此文件进行执行。二进制的可执行文件也必须有这个头操作系统才能执行。PE头里包含了标识文件类型的信息:Exe或Dll;除此之外里面还包括其生成时间以及入口方法地址(Main())等。操作系统可以通过读取这个头将托管模块加载到内存中然后调用CLR从入口方法开始执行。


n       元数据


元数据是托管模块中最重要的数据。元数据用来表述托管模块中包含的类型信息,这些信息包括类、接口、方法、字段、属性、事件等代码元素的定义信息。每个程序集都包含有元数据表,元数据表通常有两种,一种是表述代码中的类型或成员的列表;另外一种是表述源代码中引用的类型和成员的表。在模块或程序集中定义和引用的每个类型和成员都将在元数据中进行说明。当执行程序时,运行库将加载元数据,并可以通过它来发现有关代码的类、成员、继承等信息。


n       中间语言


.Net编译器将编程语言的源代码编译后生成的中间语言代码,在执行时,CLR将这些中间语言代码编译成CLR执行。


n       资源


资源是指程序在运行时所需要的资源,包括图片、字符串等。在默认情况下,一个程序集可以包含资源也可以不包含资源。如果程序集包含资源,那么程序集中会有一个叫做资源清单的结构专门来描述和连接这些资源文件,公共语言运行库在运行时会管理或加载这些资源文件。


n       程序集清单


程序集清单包含描述该程序集中各元素彼此如何关联的数据集合。这些数据包括:程序集名称、版本号、区域性、程序集中文件所有文件的列表、类型引用信息、有关被引用程序集的信息等。其中微软规定的前四项(程序集名称、版本号、区域性和强名称信息)构成了程序集的标识。查看.Net创建的任何项目拟都会发现一个叫“AssemblyInfo”的文件,这个文件就是用来设置程序集清单的,一般在创建文件时会被自动生成。

 

反射及其使用

 

提到反射,首先我们会想到中学物理,光的反射是成像的基础。如果没有光的反射,你将看不到任何东西。如果没有反射,你也不能照镜子,就算你再帅再靓,你也不知道。


对于物体来说,你可以直接查看该物体,也可以通过镜子来查看该物体。这些概念和软件技术中反射的概念很相似。在软件技术中,反射代表一种方法,一种通过间接途径来查看和访问程序集中元素的方法。

 

 

反射本质

 

C#项目在编译后生成程序集,而程序集通过记录了代码中的所有类型。假如说,我们目前有某个组件的程序集,而没有源代码,我们能不能通过一种机制从程序集中取出各种类型进行操作呢?答案是肯定的,在.Net中可以通过反射机制从程序中提取任何存在的类型,包括类、结构、委托、接口和枚举等,提取出类型后,利用反射机制我们甚至可以重新生成这些类型的对象,然后使用这些类型的成员,包括方法、属性、事件、构造方法等。在一般情况下,我们可以使用反射来执行以下任务:


n        获取程序集中有关公共类型及其公共成员的信息


n        了解代码所在的模块和程序集


n        调用程序集中类型对象公共属性或方法


要使用反射操作某个程序集中的类型,基本分为两步走:


1.      加载要反射的程序集;


2.      然后通过Type类的方法对程序集中的类型进行枚举或调用。


因为对非公共信息的访问将带来安全风险,所以.Net反射机制在默认情况下只能对程序集中的公共类型的信息或成员进行反射。

 

 

 

使用反射

 

在使用反射之前,我们首先需要加载程序集。需要使用System.Reflection命名空间下的Assembly类的Load方法或LoadFrom方法。这两个方法都是静态方法:


Assembly.Load(String 程序集名称)


例如:Assembly assA=Assembly.Load(“Shapes”);


Assembly.LoadFrom(String  程序集路径)


    例如:Assembly assB=Assembly.LoadFrom(@”F:\MyShapes\bin\Debug\MyShaps.dll”)


接下来,通过Assembly的GetType和GetTypes方法来获得加载程序集的类型了。前者只能获得程序集里一个类型,后者可以获得程序集里所有类型,原型如下:


public Type    GetType(string name) //根据类名获得该类型


public Type[]  GetTypes()  //获得程序集的所有类型


一旦获得程序集中的类型,就可以重建类型对应的对象。有关Type类的常用方法如下:

Type方法

返回类型

操作说明

GetMethod/GetMethods

MethodInfo

使用MethodInfo对象封装的方法名称、返回类型、参数、访问修饰符等

GetField/GetFields

FieldInfo

使用FieldInfo封装类型的字段名称、访问修饰符等

GetEvent/GetEvents

EventInfo

使用EventInfo封装类型的字段名称、事件处理程序、数据类型、自定义属性、声明类型和反射类型等

GetProperty/GetProperties

PropertyInfo

使用PropertyInfo封装属性的名称、数据类型、声明类型等

GetConstructor/GetConstructors

ConstructorInfo

使用ConstrucorInfo封装构造方法的名称、参数、访问修饰符等信息

 

小结:

 

在本章中,我们主要学习了:

u      组件的历史和应用

u      .Net中的组件技术

u      反射技术的使用

u      序列化

 

英语词汇:

 

英文             全文                                         中文


Attribute                                           属性


Positional                                                 状态的


Element                                            元素


Description                                              描述


Temperature                                            温度


Fahrenheit                                               华氏温度


Service                                                    服务


Import                                                     导入


Inherited                                           继承的


All                                                    所有的


Assembly                                                装配、集合、组件


Module                                            模块


Struct                                                      结构


Specify                                             指定


                                                       游戏者

 

练习项目:

 

      1.试将以前我们写的计算器的计算类生成.dll程序集,供其他地方使用。

目录
相关文章
|
2月前
|
缓存 C# Windows
C#程序如何编译成Native代码
【10月更文挑战第15天】在C#中,可以通过.NET Native和第三方工具(如Ngen.exe)将程序编译成Native代码,以提升性能和启动速度。.NET Native适用于UWP应用,而Ngen.exe则通过预编译托管程序集为本地机器代码来加速启动。不过,这些方法也可能增加编译时间和部署复杂度。
156 2
|
15天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
61 13
|
2月前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
203 0
|
2月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
101 0
|
3月前
|
C# 容器
C#中的命名空间与程序集管理
在C#编程中,`命名空间`和`程序集`是组织代码的关键概念,有助于提高代码的可维护性和复用性。本文从基础入手,详细解释了命名空间的逻辑组织方式及其基本语法,展示了如何使用`using`指令访问其他命名空间中的类型,并提供了常见问题的解决方案。接着介绍了程序集这一.NET框架的基本单位,包括其创建、引用及高级特性如强名称和延迟加载等。通过具体示例,展示了如何创建和使用自定义程序集,并提出了针对版本不匹配和性能问题的有效策略。理解并善用这些概念,能显著提升开发效率和代码质量。
131 4
|
2月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
72 0
|
2月前
|
API C#
C#实现Winform程序右下角弹窗消息提示
C#实现Winform程序右下角弹窗消息提示
118 0
|
3月前
|
Linux C# 开发者
Uno Platform 驱动的跨平台应用开发:从零开始的全方位资源指南与定制化学习路径规划,助您轻松上手并精通 C# 与 XAML 编程技巧,打造高效多端一致用户体验的移动与桌面应用程序
【9月更文挑战第8天】Uno Platform 的社区资源与学习路径推荐旨在为初学者和开发者提供全面指南,涵盖官方文档、GitHub 仓库及社区支持,助您掌握使用 C# 和 XAML 创建跨平台原生 UI 的技能。从官网入门教程到进阶技巧,再到活跃社区如 Discord,本指南带领您逐步深入了解 Uno Platform,并提供实用示例代码,帮助您在 Windows、iOS、Android、macOS、Linux 和 WebAssembly 等平台上高效开发。建议先熟悉 C# 和 XAML 基础,然后实践官方教程,研究 GitHub 示例项目,并积极参与社区讨论,不断提升技能。
112 2
|
4月前
|
缓存 NoSQL Redis
【Azure Redis 缓存】C#程序是否有对应的方式来优化并缩短由于 Redis 维护造成的不可访问的时间
【Azure Redis 缓存】C#程序是否有对应的方式来优化并缩短由于 Redis 维护造成的不可访问的时间
下一篇
DataWorks