C#教你使用反射.docx

上传人:小飞机 文档编号:4883239 上传时间:2023-05-21 格式:DOCX 页数:24 大小:208.35KB
返回 下载 相关 举报
C#教你使用反射.docx_第1页
第1页 / 共24页
C#教你使用反射.docx_第2页
第2页 / 共24页
C#教你使用反射.docx_第3页
第3页 / 共24页
C#教你使用反射.docx_第4页
第4页 / 共24页
C#教你使用反射.docx_第5页
第5页 / 共24页
亲,该文档总共24页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《C#教你使用反射.docx》由会员分享,可在线阅读,更多相关《C#教你使用反射.docx(24页珍藏版)》请在三一办公上搜索。

1、C#教你使用反射System.Reflection命名空间包括了约四十个可用于获取对象信息的类和接口。Type类是对象的所有 反射信息的基础。我们可以使用几种模式对Type对象进行检索。typeof()操作符(检索有关的信息)GetType()方法(检索有关对象的信息)举个例子:namespace Reflection_Example(using System;usering System.Reflection;public class RefExample(public int addition(int frist,int second)(return frist+second;public

2、 static int Main()(Type refType二typeof(RefExample);/类的引用RefExample objRef=new RefExample();Type objType=objRef.GetType();/对象的引用Console.WriteLine(objRef 的类型:0”,objType);Console.WriteLine(RefExample 的类型:0,refType);Console.WriteLine(RefExample 的命名空间:0,refType.Namespace); return 0;以上代码中,创建了类RefExample,并

3、为该类实例化了一个对象。方法typeof ()用于找出类RefExample的类型,GetType ()方法用于找出对象objRef的类型,Type类的Namspace属性用于检索 该类的命名空间。输出如下:objRef 的类型:Reflection_Example.RefExampleRefExample 有类型:Reflection_Example.RefExampleRefExample 的命名空间:Reflection_Example检索Type对象之后,可以检索有关所需类或对象的详细信息。以下为部份Type对象的属性和方法名称描述GetMethods()检索用于描述类的方法的Meth

4、odInfo对象的数组GetConstructors()检索类的所有构造函数GetInterfaces()检索类型的所有已经实现了的接口GetMembers()检索类型有所有成员InvokeMember()调用类型的成员IsAbstract对抽象类型返回bool值TrueIsEnum对枚举类型返回bool值TrueWCF体验之旅(1):创建一个简单的WCF程序在Microsoft提出.NET战略以来,先后推出了一系列产品和技术,这些产品和技术为我们在.NET平 台下建立企业级的分布式应用提供了很大的便利。这些技术和产品包括:.NET Remoting,XML WebSerivce, WSE(2

5、.0,3.0), Enterprise Service, MSMQ我们知道,和一个相对独立的应用不同,我们开发一个分布式应用,尤其是开发一个企业级的分布式应用,我们需要考虑较多的东西。 比如我们要考虑数据在不同的应用之间传递时采取什么样的机制,这种数据传递是否是安全的,可 靠的;如何在分布式的环境下进行异常处理;如何把分别在不同应用中执行的操作纳入同一个事 务对于我们上面提到的这些问题,这些都是开发分布式应用考虑的典型的问题。值得庆幸的是, Microsoft开发的分布式的产品能够部分的解决这些问题。.NET Remoting为我们在.NET平台下提供 了非常好的解决方案(我个人认为,.NET

6、 Remoting是.NET平台下最为成熟的分布式技术。比如相较 于另一个使用更为广泛的技术XML Web Service,它具有一些自己独特的特性:可以使用不同的传输 层协议进行通信Http & TCP;可以使用不同的消息编码方式Bianry & Text (XML);可以寄宿到 IIS 和任何一种托管的应用下Console Application、WinForm Application、WindowsService; Server端可以通过双向通信回调(Callback)客户端的操作;)XML Web Service为使我们实现跨平台的系统能够集成显得如此简单。随着技术的不断发展,相关的技

7、术规范(WS-* Specification)不断完善,XML Web Service现在已经成为使用最为广泛的分布式技术了。XML Web Service能够得到如此广泛的推广,这得得益于Microsoft先后两次推出的Web Service Enhancement(WSE 2.0、WSE 3.0)。如果没有WSE,单纯的asmx下的如此的担保和不可靠。WSE为Web Service解决了几大难题:Security、Reliable Messaging、transaction Handling 以及大数据的有效传输。 MSMQ作为一种简单而有效的机制为不同应用之间数据的传递提供了保障。其实,

8、通过合理利用上面这些分布式的技术完全可以为我们建立的一套适合不同层次需要的分布式构 架。但这里面仍然存在一些问题,那就是上面这些技术和产品只能解决某一方面的问题;比如.NET Remoting虽然在.NET平台下是一个很好的依靠,但是考虑到他不能提供不同平台之间的互操作性。 另外,这些技术适合用了完全不同的编程方式,使得我们很难从容地从其中一种转移到另一种上来。 基于这些原因,我们需要一套全新的技术整合以上都这些技术,于是我们有了今天的WCFWindows Communication Foundationo WCF建立一套框架,是我们通过一致的编程模式,使用不同的技术构建我们的分布式应用。虽然

9、很早开始接触WCF,但所学的总是零零碎碎。现在开始系统地研究WCF,希望与大家一同分享我 的一些所得,同时希望能通过这样的一个机会与大家一些探讨WCF,不对的地方希望大家指正。 一开始我们先建立一个简单程序看WCF如何工作:1、建立整个应用的简单构架整个构架如图所示,这个 Solution 由 5 个 Project 组成:Artech.WCFService.Contract; Artech.WCFService.Service; Artech.WCFService.Hosting; Artech.WCFService.Client; http:/localhost/WCFService。Ar

10、tech.WCFService.Contract: Class Library Project,用来保存 Contract (Service Contact、 Message Contract、Data Contract),之所以把Contract独立出来的原因是考虑到他同时被Server 端Service本身和Service Hosting和Client端使用。(现在很多的参考书,包括MSDN都使用ServiceModel Metadata Utility Tool (Svcutil.exe)这样的一个工具来访问 Service 的 Metadata Endpoint来生成我们的客户段代码,

11、这些代码就包括Service Contract (一般是一个Interface), 实现了这个 Contract 的 Proxy Class (一个集成自 System.ServiceModel.CientBase 的一个 Class) 和相应的Configuration。这个工具确实给我提供了很大的方便。但我不推荐使用这样的方法(我天 生不倾向对于这些代码生成器),因为我觉得,在Contract可得的情况下一比如Service和Client 都是自己开发,让Service和Client实现的Contract是同一个Contract能够保证一致性。这个 Project 弓|用 System.S

12、erviceModel DLL。Artech.WCFService.Service: Class Library Project, Service 的业务逻辑,这个 Project 引用 Artech.WCFService.Contract Project 和 System.ServiceModel DLL。Artech.WCFService.Hosting: Console Application,用于以 Self-Hosting 的方式 Host Service。 这个 Project 弓 |用 Artech.WCFService.Contract 和 Artech. Project WC

13、FService.Service。Project 和 System.ServiceModel DLL。Artech.WCFService.Client: Console Application,用以模拟现实中的调用 Service 的 Clinet o 这个 Project 弓 |用 Artech.WCFService.Contract Project 和 System.ServiceModel DLL。http:/localhost/WCFService: Web Site Project,用于模拟如何把 Service Host 到 IIS 中。这 个 Project 弓 |用 Artec

14、h.WCFService.Contract、Artech.WCFService.Service 和 System.ServiceModel DLL。2、创建 Service Contract在这个例子中我们建立一个简单的案例,做一个计算器,假设我们只要求他做简单的加法运算就可以 了。在 Artech.WCFService.Contract 添加一个 interface,名称叫做【Calculator。using System.Collections.Generic;using System.Text;using System.ServiceModel;namespace Artech.WCFS

15、ervice.Contract(ServiceContractpublic interface ICalculator(OperationContract double Add(double x, double y); 使一个 Interface 成为 Service Contract 的方法很简单,就是把 ServiceContractAttribute 应用到 这个interface上,并在代表单个Operation的方法上应用OperationContractAttribute。这个使 用Custom Attribut e的编程模式被称为声明式的编程(Declarative)方式, 他在

16、.NET Framework 1.1以前用到的地方还不是太多,在.NET Framework 2.0,尤其是NET Framework 3.0中,这种方式 已经变得随处可见了。我们可以把Contract定义成一个Interface,也可以把它定义到一个Class中 这个Class中既 包涵Service本身又作为一个Contract而存在。但我推荐使用第一种方法 Serive和Contract 相分离。在WCF中,Contract的功能实际上就定义一个Service包含哪些可用的Operation,以及的每个 Opertaion的方法签名。从消息交换(Message Exchange)的角度讲

17、,Contract定义了调用相应的 Serive采取的消息交换的模式(Message Exchange Pattern - MEP),我们经常使用的MEP包括三 种:Oneway, Request/Response,和Duplexo因为调用Service的过程实际就是消息交换的过程, 以常见的Request/Response为例。Client调用某个方面远程访问Service,所有的输入参数被封装 到Request Soap Message并被发送到Service端,Service端监听到这个Soap Request,创建相应 的 Service Object 并调用相关的操作,最后将 Res

18、ult (这可以是 Return Value, Reference Parameter 和Output Parameter)封装成Soap Message发送回Client端。这里需要注意,如果采用的是 Request/Response 的模式,即使相应的操作没有 Return Value, Reference Parameter 和 Output Parameter (它被标记为void),Service仍然会返回一个空的Soap Message给Client端。3、创建 Service前面我们已经创建了我的Artech.WCFService.Contract。其实我们从Contract这个

19、单词上讲,它就 是一种契约,一种承诺。他表明在上面签了字你就的履行Contract上义务。Service就是这样一个 需要履行Contract义务的人。在这个例子中,Contract以Interface的方式定义的一些Operation。 作为Service,在Contract上签字的方式就是实现这样的一个Interface。下面的Service得到code, 很简单。using System;using System.Collections.Generic;using System.Text;using System.ServiceModel;using Artech.WCFService.

20、Contract;namespace Artech.WCFService.Service (public class CalculatorService:ICalculator(#region ICalculator Memberspublic double Add(double x, double y) (return x + y;#endregion4、Hosting Service就像Remoting 一样,我们继承自System.MarshalByRefObject的对象必须Host到某一个运行的进程 中,他才开始监听来自Client端的请求,当Client才能通过Proxy远程的调用

21、,Remoting Infrastructure监听到来自Client端的请求,他会激活相应的remote Object (我们只考虑Server Activate ObjectSAO)。实际上对于WCF Service也需要一个Host环境才有其发挥作用的舞台。就像 Remoting 一样,你可以使用任何一种Managed ApplicationConsole Application、WinFormApplication、ASP.NET Application作为它的 Host 环境。你甚至可以用它 Host 到 WindowsService中和IIS中(后面我将会讲到如何做)。我们知道WC

22、F中,Client端和Service端是通过Endpoint来通信的,Endpoint有包含3个部分,经 典地称为ABC。A代表Address,它包含一个URI,它指明Service存在于网络的某个地方,也就是说它为Client断 指明在什么地方去找到这个Service。很多人认识Address仅仅只是一个具有Identity的URI,实际 上不然,Address不止于此,它还包含一些Header,这些信息在某些情况下对于如何寻址有很大的 意义(比如在client的最终Service之间还有一些Intermediary节点的情况下)。在.NET中,Address 用 System.Servic

23、eModel.EndpointAddress 来表示。B代表Binding,Binding封装了所有Client和Service段消息交换的通信细节。比如他定义了通信 应该采用的Transport 一比如我们是因该采用Http,TCP,Named Pipe或者是MSMQ;通信的内容应该采取怎样的编码比如是Text/XML, Binary还是MTOM。以上这些都得一个Binding所必须定义的 内容,此外,Binding还可以定义一些其他的有关通信的内容,比如Security,Reliable Messaging, Session,Transaction等等。正因为Binding对于通信的重要性

24、,只有Service端的Binding和Client 的Binding相互匹配的时候,他们之间在可以相互通信。如何使Client Binding匹配Service Binding 呢?最简单也是最直接的方法就是使用相同的Binding。WCF为我们定义了一系列的System Defined Binding,这些 Binding 在 Transport, Interoperability, Security, Session Support,以及 Transaction Support方面各有侧重。基本上WCF为我们定义的这些Binding已经够我们使用的了, 如果,实在满足不了要求,你还可以建

25、立自己的Custom BindingoC代表Contract这在上面已经提及,这里不再累赘。usingusingusingusingusingusingusing(class(Host的本质就是把一个Service置于一个运行中的进程中,并以Endpoint的形式暴露出来,并开始 监听来自Client端的请求。这里值得注意的是,同一个Service可以注册若干不同的Endpoint,这 样不同的Client就可以以不同的方式来访问同一个Service.比如,同一个Intranet的Client可 以以TCP的方式访问Service,另一个存在已Internet中的Client则只能以Http的

26、方式访问。System;System.Collections.Generic;System.Text;System.ServiceModel;Artech.WCFService.Contract;Artech.WCFService.Service;ProgramSystem.ServiceModel.Description; namespace Artech.WCFService.Hosting static void Main(string args)(HostingServiceViaCode();static void HostingServiceViaCode()(/Specify t

27、he base AddressUri baseUri = new Uri(http:/localhost:8080/calculatorService);Service and/create a new ServiceHost object and specify the correspondingbase Address /It is recommended to apply the using pattern to make surethe sevice host can be closed properly.using (ServiceHost calculatorServiceHost

28、 = new ServiceHost(typeof(CalculatorService), baseUri) (/Create a Binding for Endpoint.BasicHttpBinding Binding = new BasicHttpBinding();/Create a Service Endpoint by specify the Address (it is absolute or relative path based on the base Address, the empty string indicates the Address equals base Ad

29、dress),/Binding(the basicHttpBindingcreated) and Contrace(it is now the type info of the contractinterface)calculatorServiceHost.AddServiceEndpoint(typeof(ICalculator),Binding, string.Empty);/Such a segment of code snip shows how to make themetadata exposed to the outer world by setting the Service

30、metadatabehavior/Find the Service metadata behavior if exists, otherwize returnnull.ServiceMetadataBehavior behavior =/If the ServicecalculatorServiceHost.Description.Behaviors.Find();metadata behavior has not to added to the Service. we will create a new one and evaluate the HttpGetEnabled&HttpGetU

31、rl to make outer world can retrieve to metadata.if (behavior = null)(behavior = new ServiceMetadataBehavior();behavior.HttpGetEnabled = true;/HttpGetUrl is absolute or relative based on base Address behavior.HttpGetUrl = baseUri;er/We must add the new behavior created to the behavior collection, oth

32、erwize it will nev take effect.calculatorServiceHost.Description.Behaviors.Add(behavior);/if the metadata behavior exists in the behavior collection, we just needto evaluate the HttpGetEnabled&HttpGetUrlelse(behavior.HttpGetEnabled = true;behavior.HttpGetUrl = baseUri;/Add the opened event handler t

33、o make a friendly message displayed afteropening the Service host indicating the Service begin to listen to request from Clients.calculatorServiceHost.Opened += delegate( Console.WriteLine(Calculator Service begin to listen via the Address:0,calculatorServiceHost.BaseAddresses0.ToString(); ;/Open th

34、e Servicehost make it begin to listen to the Clients.calculatorServiceHost.Open();Console.Read();我们现在可以单独运行Hosting Projet,以下是运行后的截图。当Hosting启动之后,由于我们为它开启了 Http Enabled, Hosting为专门创建一个Metadata Endpoint,通过访问这个 Endpoint,我们可获取 Service 相关的 Metadata。像 ServiceModel Metadata Utility Tool (Svcutil.exe)这得工具就是

35、通过获取Metadata来帮我们生成相应的客户端代码和配 置文件。当Hosting被启动之后,我们可以在IE中输入Metadata Endpoint的Address来测试Service 的可访问性。如下图。以上我们完全以代码的方式Host 一个已经创建的Service。在这个例子中,Endpoint的所有信息都 在代码中指定。实际上真正的项目开发之中,我们基本上不采用这样的方法。这是因为,Service的 Address s以及Binding信息在开发阶段和部署阶段往往是不一样的。所以我们通常的做法是把这 些信息放在Config文件中,这样我们可以根据实际的需求改变存储于Config文件中的信

36、息,比如我 们把Service移植上另外的位置,我们只要改变Endpoint的Address配置信息就可以了;再比如, 我们把原来存在Intranet的Service放到Internet上,原来可能基于TCP的Binding必须改成基于 Http的Binding,在这种情况下,我们依然可修改配置文件就可以了,这样的改动通常是很小的,并 且修改了配置文件之后我们不需要对现有的代码进行重编译和重部署,它们可以其实生效。下面我们来看看如何创建基于Configuration的Hosting。首先,在Artech.WCFService.Hosting中创建App.config,并编写如下结构的配置信息。

37、http:/localhost:8888/GeneralCalculator/然后我们相应地改变我们的Hosting代码,现在由于我们的Endpoint的信息都放在我们的配置文件 中,所以我们可以较大的简化我们的Hosting代码。using System;using System.Collections.Generic;using System.Text;using System.ServiceModel;using Artech.WCFService.Contract;using Artech.WCFService.Service;using System.ServiceModel.Des

38、cription;namespace Artech.WCFService.Hosting(class Program(static void Main(string args)(using (ServiceHost calculatorServiceHost =new ServiceHost(typeof(CalculatorService)(calculatorServiceHost.Opened += delegate ( Console.WriteLine(Calculator Servicebegin to listen via the Address:0,calculatorServ

39、iceHost.BaseAddresses0.ToString(); ;calculatorServiceHost.Open();Console.Read();当 calculatorServiceHost.Open();被调用之后,系统会查看 calculatorServiceHost 对应的 Service 的类型,结果发现它的类型是 Artech.WCFService.Service. CalculatorService (在 ServiceHost 被创建时最为第一个传入参数);然后会在config文件中Services部分中找name属性和这个Service type相匹配,找到之后

40、,把它host进来,然后添加它在配置文件中定义的所有的Endpoint,并设置 在配置文件中定义的所有Binding以及Behavior。现在我们运行Hosting,将会得到同上面一样的 结果。同样,在IE中输入Metadata Endpoint的Address,也会看到上解图一样的显示。5、创建 Client到现在为止,Service端的工作已经完成,当你启动Hosting的时候,一个可用的Service就已经存 在了。现在所做的事情是如何创建我们的客户段程序去使用这个Service。几乎所有的WCF的书,其 中包括MSDN都是叫你如何使用Service Utility这样的一个工具来帮你生

41、成客户端代码和配置信息。 为了让我们能够清晰的Client的整体内容,我们现在选择手工的方式来编写这样的部分代码。几乎所有分布式的调用都有这样的一个概念,调用的具体实现被封装在Server端,Client不可能也 不需要了解这个具体实现,它所关心的就是我如何去调用,也就是说Cient需要的不是Service的实 现,而是一个interface。WCF也是一样,Client不需要了解Service的具体实现,它只需要获得 Service的Contract,已经如何与Service通信就足够了。说到Contract和通信,我们很自然地会 想到Endpoint,不错,Endpoint恰恰给我们提供这

42、两个方面的内容。所以到现在我们可以这样说, 这样在Client建立和Serivce端相匹配的Endpoint,Client就可以调用它所希望的Service。前面 提到Endpoint包括三个部分,Address, Binding, Contract那我们现在来看看Client如何获得 这3要素的信息。在 System。Service。Model 命名空间里,定义了一个类 abstract class ClientBase,给我们调用 Service提供极大的便利。我们只要是我们的Client继承这样一个类,并为它指定Endpoint的三要 素就一切OK 了,下面我们来看看我们可以以那些方式来

43、指定这些内容1、Conract:我们看到了 ClientBase是一个Generic的类,我们在创建一个继承自这个类的时候必 须给它指定特定的TChannel.我们可以把Contract对应的类型作为Client的generic类型。2、Binding和Address:和Service端的Endpoint 一样,我们可以把相关的信息放在我们的Client 端代码里面,也可以放在Client的Config里面。那个这些数据如何应用要我们创建的派生自 ClientBase的类的对象上呢。其实很简单,ClientBase给我们定义了若干重载的构造函数,我们只 要定义我们相应的构造函数应简单地调用基类

44、的构造函数。下面列出了 ClientBase定义的全部的构 造函数。protected ClientBase():这个构造函数没有任何的参数,它用于Endpoint的信息全部存放于Config protected ClientBase(InstanceContext callbackInstance):指定一个 Callback instance 用于 Service 回调 Client 代码,这用 Deplex Communicationoprotected ClientBase(string EndpointConfigurationName):指定一个 ID,它标识 configurat

45、ion 文件中定义的某一个Endpointo这个方法在使用不同的Endpoint调用同一个Service的情况下用到 的比较多。ClientBase(Binding Binding, EndpointAddress remoteAddress);显示的指定 Binding 和 Address ClientBase(InstanceContext callbackInstance, string EndpointConfigurationName) ClientBase(string EndpointConfigurationName, EndpointAddress remoteAddress

46、) ClientBase(string EndpointConfigurationName, string remoteAddress) ClientBase(InstanceContext callbackInstance, Binding Binding, EndpointAddress remoteAddress)ClientBase(InstanceContext callbackInstance, string EndpointConfigurationName, EndpointAddress remoteAddress)ClientBase(InstanceContext cal

47、lbackinstance, string EndpointConfigurationName, string remoteAddress)介绍完ClientBase后,我们来创建我们自己的CalculatorClient。下面的相应的Codeusing System;using System.Collections.Generic;using System.Text;using System.ServiceModel;using System.ServiceModel.Channels;using Artech.WCFService.Contract;namespace Artech.WCFService.Client(class CalculatorClient:ClientBase,ICalculator(internal CalculatorClient():base()( #region ICalculator Memberspublic double Add(double x, double y)(return this.Channel.Add(x, y);#endregion上面的例子中我们仅仅定义了一个无参的构造函数,因为我们会把所有的Endpoint信息放在Config 文件里面:http:/localhost: 8080/WCFSe

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号