资讯

展开

WCF学习笔记

作者:快盘下载 人气:


as wo konw 。Net一直在分布式领域做的不好,这就使得NEt有了很大的限制。而WCF的出现必将引领着新的时代。

我学这个呢,呵呵,才俩天。不过思路是率清楚了。

WCF主要包括以下几个内容:

Artech.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来生成我们的客户段代码,这些代码就包括Service Contract(一般是一个Interface),实现了这个Contract的Proxy Class(一个集成自System.ServiceModel.CientBase的一个Class)和相应的Configuration。 这个工具确实给我提供了很大的方便。但我不推荐使用这样的方法(我天生不倾向对于这些代码生成器),因为我觉得, 在Contract可得的情况下-比如Service和Client都是自己开发,让Service和Client实现的Contract是同一个Contract能够保证一致性。这个Project引用System.ServiceModel 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 WCFService.Service。Project和System.ServiceModel DLL。Artech.WCFService.Client:Console Application, 用以模拟现实中的调用Service的Clinet。这个Project引用Artech.WCFService.Contract Project 和System.ServiceModel DLL。​​http://localhost/WCFService​​: Web Site Project, 用于模拟如何把Service Host到IIS中。这个Project引用Artech.WCFService.Contract、Artech.WCFService.Service和System.ServiceModel DLL。 2 创建Service Contract在这个例子中我们建立一个简单的案例,做一个计算器, 假设我们只要求他做简单的加法运算就可以了。在Artech.WCFService.Contract添加一个
interface,名称叫做ICalculator。
using
System.Collections.Generic;

using
System.Text;

using
System.ServiceModel;


namespace
Artech.WCFService.Contract
{
[ServiceContract]

public

interface
ICalculator
{
[OperationContract]

double
Add(
double
x,
double
y);
}
}
使一个Interface成为Service Contract的方法很简单,就是把ServiceContractAttribute应用到这个interface上,并在代表单个Operation的方法上应用OperationContractAttribute。这个使用Custom Attribute的编程模式被称为声明式的编程(Declarative)方式, 他在.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)的角度讲,Contract定义了调用相应的Serive采取的消息交换的模式(Message Exchange Pattern - MEP),我们经常使用的MEP包括三种:Oneway, Request/Response,和Duplex。因为调用Service的过程实际就是消息交换的过程, 以常见的Request/Response为例。Client调用某个方面远程访问Service,所有的输入参数被封装到Request Soap Message并被发送到Service端, Service端监听到这个Soap Request,创建相应的Service Object并调用相关的操作,最后将Result(这可以是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这个单词上讲, 它就是一种契约,一种承诺。 他表明在上面签了字你就的履行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.Contract;




namespace
Artech.WCFService.Service

{


public

class
CalculatorService:ICalculator

{


#region
ICalculator Members





public

double
Add(
double
x,
double
y)

{


return
x
+
y;

}




#endregion


}

}
4.Hosting Service就像Remoting一样,我们继承自System.MarshalByRefObject 的对象必须Host到某一个运行的进程中, 他才开始监听来自Client端的请求,当Client才能通过Proxy远程的调用,Remoting Infrastructure监听到来自Client端的请求,他会激活相应的remote Object(我们只考虑Server Activate Object——SAO)。实际上对于WCF Service也需要一个Host环境才有其发挥作用的舞台。就像Remoting一样,你可以使用任何一种Managed Application——Console Application、WinForm Application、ASP.NET Application——作为它的Host环境。 你甚至可以用它Host到Windows Service中和IIS中(后面我将会讲到如何做)。我们知道WCF中,Client端和Service端是通过Endpoint来通信的,Endpoint有包含3个部分,经典地称为ABC.A代表Address,它包含一个URI,它指明Service存在于网络的某个地方,也就是说它为Client断指明在什么地方去找到这个Service。很多人认识Address仅仅只是一个具有Identity的URI,实际上不然, Address不止于此, 它还包含一些Header,这些信息在某些情况下对于如何寻址有很大的意义(比如在client的最终Service之间还有一些Intermediary节点的情况下)。 在.NET中, Address用System.ServiceModel.EndpointAddress 来表示。B代表Binding,Binding封装了所有Client和Service段消息交换的通信细节。比如他定义了通信应该采用的Transport-比如我们是因该采用Http, TCP,Named Pipe或者是MSMQ;通信的内容应该采取怎样的编码——比如是Text/XML,Binary还是MTOM。以上这些都得一个Binding所必须定义的内容, 此外,Binding 还可以定义一些其他的有关通信的内容, 比如Security,Reliable Messaging, Session, Transaction等等。正因为Binding对于通信的重要性,只有Service端的Binding和Client的Binding相互匹配的时候,他们之间在可以相互通信。如何使Client Binding 匹配Service Binding呢?最简单也是最直接的方法就是使用相同的Binding。WCF为我们定义了一系列的System Defined Binding,这些Binding在Transport,Interoperability,Security,Session Support,以及Transaction Support方面各有侧重。基本上WCF为我们定义的这些Binding 已经够我们使用的了,如果,实在满足不了要求, 你还可以建立自己的Custom Binding。C 代表Contract这在上面已经提及,这里不再累赘。Host的本质就是把一个Service 置于一个运行中的进程中,并以Endpoint的形式暴露出来,并开始监听来自Client端的请求。这里值得注意的是,同一个Service可以注册若干不同的Endpoint,这样不同的Client就可以以不同的方式来访问同一个Service.比如,同一个Intranet的Client可以以TCP的方式访问Service,另一个存在已Internet中的Client则只能以Http的方式访问。
using
System;


using
System.Collections.Generic;


using
System.Text;


using
System.ServiceModel;


using
Artech.WCFService.Contract;


using
Artech.WCFService.Service;


using
System.ServiceModel.Description;




namespace
Artech.WCFService.Hosting

{


class
Program

{


static

void
Main(
string
[] args)

{

HostingServiceViaCode();

}






static

void
HostingServiceViaCode()

{


//
Specify the base Address



Uri baseUri
=

new
Uri(
"
http://localhost:8080/calculatorService
"
);


//
create a new ServiceHost object and specify the corresponding Service and base Address


//
It is recommended to apply the using pattern to make sure the sevice host can be closed properly.




using
(ServiceHost calculatorServiceHost
=

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 Address),


//
Binding(the basicHttpBinding created) and Contrace(it is now the type info of the contract interface)



calculatorServiceHost.AddServiceEndpoint(
typeof
(ICalculator), Binding,
string
.Empty);




//
Such a segment of code snip shows how to make the metadata exposed to the outer world by setting the Service metadata behavior


//
Find the Service metadata behavior if exists, otherwize return null.



ServiceMetadataBehavior behavior
=
calculatorServiceHost.Description.Behaviors.Find
<
ServiceMetadataBehavior
>
();




//
If the Service metadata behavior has not to added to the Service. we will create a new one and eval(behavior
==

null
)

{

behavior
=

new
ServiceMetadataBehavior();

behavior.HttpGetEnabled
=

true
;


//
HttpGetUrl is absolute or relative based on base Address



behavior.HttpGetUrl
=
baseUri;


//
We must add the new behavior created to the behavior collection, otherwize it will never take effect.



calculatorServiceHost.Description.Behaviors.Add(behavior);

}


//
if the metadata behavior exists in the behavior collection, we just need to eval(
"
Calculator Service begin to listen via the Address:{0}
"
, calculatorServiceHost.BaseAddresses[
0
].ToString()); };


//
Open the Service host make it begin to listen to the Clients.



calculatorServiceHost.Open();



Console.Read();

}

}

}

}


这样服务器段就做好了,可以运行了。

加载全部内容

相关教程
猜你喜欢
用户评论
快盘暂不提供评论功能!