只使用代码而不用配置文件的情况不适合IIS为宿主的情况,IIS宿主必须使用配置文件配置WCF的ServiceHost。

1、服务端

1.1.    准备Contract和实现Contract的服务

很简单的一个Contract(Interface)和实现这个Contract(实现这个接口的类)的服务。

这是VS2005中使用add new item,选WCF Service后自动生成的一个模板例子服务代码。

[ServiceContract()]

public interface IService

{

[OperationContract]

string MyOperation1(string myValue);

}

public class Service : IService

{

public string MyOperation1(string myValue)

{

return "Hello: " + myValue;

}

}

1.2.    建立ServiceHost

一般使用public ServiceHost(Type serviceType, params Uri[] baseAddresses)构造方法建立ServicesHost。

参数:

Type serviceType -- 为实现了某些Contract的类的类型,为这个服务主机要host的服务。

params Uri[] baseAddresses -- 为任意数量的baseAddress。

Uri baseAddress = new Uri("http://localhost:8080/WCFService/Service");

//Instantiate new ServiceHost

myServiceHost = new ServiceHost(typeof(Service), baseAddress);

一个ServiceHost内只能驻留一个Service类,但是这个Service类可以实现多个Contract,每个Contract都能通过一个或多个(不同的bind)Endpoint向客户端暴露。

进程、应用程序域和ServiceHost

Dotnet出现之前,资源的分配是以进程为单位,进程是应用程序的安全边界,进程之间不能直接访问,一个进程的崩溃也不会直接影响到别的进程。

但是,进程有个缺点,为了维护进城的安全上下文,耗费的资源很大。

后来引入了线程,一个进程中可以包含多个线程,同一进程里的线程共享资源、切换方便,但是线程不具有隔离性,一个线程的崩溃将会影响到其他线程。

Dotnet引入了应用程序域,是介于进程和线程之间的逻辑概念,它既有进程的安全隔离性的优点,又有线程轻巧快捷的特性。应用程序域跟进程一样,一个应用程序域不能直接访问另一个应用程序域的资源,一个应用程序域的崩溃也不会影响其他应用程序域。同时应用程序域占用的资源比进程少的多,应用程序直接的切换也很快捷。

一个进程中可以包含多个应用程序域,一个应用程序域内有可以包含多个线程。

所有的win可执行文件(exe、dll等等)的开头都是一个被称作(Portable Executable)结构,dotnet的可执行文件同样也是用了这个PE头(结构同以前的兼容,只是增加了些内容),下面是dotnet的PE主要包含的信息:

运行这个可执行文件要求的最低CLR版本号

是否使用了强名称

程序的入口地址

可执行文件的元数据(metadata

简单的dotnet的exe可执行文件的载入过程:

windows程序载入器(os loader)读取exe文件的PE头,获取入口地址,exe入口地址其实是个跳转指令指向mscoree.dll中的_corexemain函数。

_corexemain函数实际上是个入口程序,一般被称作shim(填隙物)。由这个入口程序来决定使用哪个类型的CLR(服务器类型或工作站类型),和什么版本的CLR来运行这个exe。

确定了使用哪个CLR后,动态载入这个CLR,把控制权交给CLR。

CLR拿到控制权后,首先创建一个工作进程,以便在进程内创建应用程序域。

CLR创建工作进程后,首先会创建一个缺省应用程序域,这个缺省应用程序域一般不用来加载用户代码。之后,开始在在新的应用程序域中加载用户代码,并运行。

具体到承载WCF的console应用,是个dotnet的exe程序,运行后被CLR加载到一个应用程序域后,ServiceHost就在这个应用程序内运行,如下图:

在一个Application Domain中可以实例化多个 ServiceHost 实例,但每个应用程序域内只有一个 ServiceHost 实例更便于操作。您可以在一个宿主内使用多个端点公开多个服务接口。

1.3.    给ServiceHost添加Endpoint

Endpoint是直接暴露给客户端就行通讯的接口,经典的一个Endpoint可以用ABC来描述,即address – 这个Endpoint对外的访问地址,binding – 这个Endpoint是通过什么样的通讯手段暴露给客户端的,Contract -- 这个Endpoint对外暴露的是哪个Contract。

通过两个方法给ServiceHost添加Endpoint

1.3.1.    ServiceHost.AddServiceEndpoint

AddServiceEndpoint方法有8种重载,ServiceHost提供了四种:

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);

ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri);

ServiceHost的父类ServiceHostBase也提供了四种:

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri);

ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri);

其中参数implementedContract为Contract的完全名称,即名称空间.类名。

myServiceHost.AddServiceEndpoint(typeof(WCFService.IService), new BasicHttpBinding(), "");

1.3.2.    ServiceHost.Description.Endpoints.Add(ServiceEndpoint  item)

ServiceHost.Description是一个ServiceDescription类型的对象。

ServiceDescription是一个Service在内存中的一个完整的描述,包括服务的所有Endpoint,和每个Endpoint的各自的address、binding、contract和behaviors。

使用此方法先要根据Endpoint的ABC构造一个ServiceEndpoint 对象。

ServiceEndpoint(ContractDescription contract, Binding binding, EndpointAddress address)

其中ContractDescription这样通过ContractDescription的静态方法GetContract构造:

ContractDescription.GetContract(Type contractType);

ServiceEndpoint myServiceEndpoint =  newServiceEndpoint(ContractDescription.GetContract(typeof(WCFService.IService)), new BasicHttpBinding(), newEndpointAddress(baseAddress));

myServiceHost.Description.Endpoints.Add(myServiceEndpoint);

1.4.    视需要给ServiceHost添加behavior

ServiceHost.Behaviors是一个IServiceBehavior类型的对象集合。

IserviceBehavior 提供了一个在整个服务范围内修改或则插入定制扩展的机制。

如果需要把服务通过WSDL对外暴露对服务的Metadata描述,就需要加一个ServiceMetadataBehavior类型的Behavior:

ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

behavior.HttpGetEnabled = true;

behavior.HttpGetUrl = new Uri("http://localhost:8001/");

myServiceHost.Description.Behaviors.Add(behavior);   //myServiceHost是ServiceHost实例

要发布Metadata,需要对外提供一个Http的地址,由HttpGetUrl 属性指定。

如果HttpGetUrl指定了绝对地址,那么对外发布Metadata的地址就为:HttpGetUrl 后加?wsdl。

如果HttpGetUrl指定了相对地址,那么对外发布Metadata的地址就为:ServiceHost的baseAddress + HttpGetUrl 后加?wsdl。

如果没有设置HttpGetUrl,那么Metadata的地址就是ServiceHost的baseAddress后加?wsdl

不管HttpGetUrl属性怎么设置,ServiceHost的baseAddress总是作为这个ServiceHost提供服务的描述页面的URL。

1.5.    打开ServiceHost,开始提供服务

ServiceHost构建好了,添加了需要的Endpoint、behavior后,使用ServiceHost.Open()方法开发ServiceHost实例,开始对外提供服务。

2、客户端

2.1.    引用service

客户端要访问服务端的服务,首先要知道服务端的服务提供了什么方法,就是要知道服务的Contract。如何取得服务端的Contract有几种方法

2.1.1.    直接把服务端的Contract的副本拷贝到客户端

这个方法是最原始的一种方法,这样保证了服务端跟客户端使用同一份Contract。但是,这个方法不值得提倡,因为双方的Contract是同一个来源,但是毕竟是两个独立的物理存在,它们之间只能人为的来保证其一致性。

2.1.2.    使用Svcutil.exe工具获得服务端Contract并生成本地服务代理类

大家知道,web service是通过WSDL对外提供服务的描述,以便客户端能够通过wsdl知道这个web service所包含的方法、方法的签名等等信息,客户端通过wsdl就能知道怎么去调用这个web service。

到了WCF时代,微软依然采用WSDL来提供对WCF服务的描述。

前面服务端给ServiceHost添加了一个ServiceMetadataBehavior类型的Behavior,目的就是让服务端对外提供WSDL形式的服务Metadata描述。

微软提供了Svcutil.exe工具用来通过WSDL生成客户端Contract和代理功能:

Svcutil.exe httpbaseAddress

httpbaseAddress 就是服务端设置的http的baseAddress。当然前提是服务端在ServiceHost.Behaviors添加一个ServiceMetadataBehavior类型的Behavior,并设置HttpGetEnabled属性为true,允许对外暴露服务端Metadata描述

运行Svcutil.exe后,生成两个文件,一个是WCF配置文件,一个是包含了服务端Contract和对应于服务端service的本地代理类的cs文件。

生成的cs文件有下面的规律:

l         引用服务端的服务所涉及的Contract(Interface类型)基本都原样引用到客户端(可能会自动给Contract添加一些Attribute)。

l         服务端的Endpoint到了客户端,每个具有不同Contract的Endpoint都会在客户端生成一个代理类。Contract相同,binding不同的Endpoint使用同一个客户端代理类。

2.1.3.    在客户端项目中添加Service reference

在vs2005中安装了WCF的extention后,在项目的References上点击右键,会多出来一个“Add Service Reference”的选项,这就是用来引用WCF服务的,引用地址就是服务端设置的http的baseAddress。

在这里引用WCF服务,跟使用Svcutil.exe命令一样,会在项目中生成同样的两个文件。

2.2.    生成客户端service代理实例

引用服务后,客户端生成了配置文件和包含了Contract和本地代理类的cs文件,这里我们完全不使用配置文件,所以把生成的配置文件从项目中排除。

2.2.1.    使用ChannelFactory Generic

使用ChannelFactory Generic类的CreateChannel静态方法CreateChannel,返回一个客户端代理。

static TChannel CreateChannel(Binding binding, EndpointAddress endpointAddress);

localhost.IService proxy = ChannelFactory<localhost.IService>.CreateChannel(new BasicHttpBinding(), newEndpointAddress("http://localhost:8080/WCFService/Service"));

这个方法包含了一个Endpoint的ABC三个主要元素:

Address – new EndpointAddress("http://localhost:8080/WCFService/Service")是地址。

Bingding – new BasicHttpBinding() 是绑定。

Contract -- localhost. IService是引用服务后在在客户端生成的来自服务端的Contract(interface类型)。

2.2.2.    直接使用引用服务后形成的本地代理类

上面使用ChannelFactory的CreateChannel静态方法建立代理只使用到了引用WCF服务后在客户端生成的Contract,同时前面也说过,引用WCF服务后,还会在同时给每个Contract不同的Endpoint生成一个继承自System.ServiceModel.ClientBase的本地代理类。

客户端可以直接使用多个重载的代理类构造方法实例化这些代理类。如果不使用配置文件,使用这个构造方法:

SecondServiceClient(Binding binding, EndpointAddress remoteAddress)

其中SecondServiceClient为本地的一个代理类。实例化一个代理类的代码是这样的:

localhost.ServiceClient proxy = new localhost.ServiceClient(new BasicHttpBinding(), newEndpointAddress("http://localhost:8080/WCFService/Service"));

同样,实例化的proxy也包含了一个Endpoint的ABC三个主要元素:

Address – new EndpointAddress("http://localhost:8080/WCFService/Service")是地址。

Bingding – new BasicHttpBinding() 是绑定。

Contract –localhost.ServiceClient本身就是继承自某一个Contract的

2.3.    使用代理实例的方法

有了WCF的本地代理类实例,就可以使用服务提供的方法了。

string result = proxy.MyOperation1("myFirstWCF");

完全不使用配置文件的例子代码下载:http://files.cnblogs.com/chnking/NoConfigWCF.rar



本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2011/08/10/2133498.html,如需转载请自行联系原作者

WCF系列(一) -- 完全不使用配置文件构建和使用WCF服务相关推荐

  1. WCF系列(二) -- 使用配置文件构建和使用WCF服务

    当然,配置一个ServiceHost除了上面说的完全使用代码的方式,更好的方式是使用配置文件,把一些可能需要修改的属性跟代码分离,放到配置文件中,这样可以提供服务配置的灵活性,也更容易维护. 看看前面 ...

  2. spring配置文件_SpringBoot入门建站全系列(二十三)配置文件优先级及自定义配置文件...

    SpringBoot入门建站全系列(二十三)配置文件优先级及自定义配置文件 一.概述 Spring Boot允许多种配置来源,官网是这样说的: Spring Boot使用一种非常特殊的Property ...

  3. 一步一个脚印学习WCF系列之WCF概要—WCF与SOA(二)

    阅读目录 一:什么是WCF? 二:WCF与SOA之间的关系 三:对比SQA架构和非SQA架构    一:什么是WCF? .Windows Communication Foundation WCF全称叫 ...

  4. mysql分布式事务wcf_[转载]WCF系列_分布式事务(下)

    浏览到chnking的WCF的分布式事务处理不错,转载过来分享一下.1. WCF分布式事务例子这里也用转账的例子说事. 用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B ...

  5. WCF系列教程之WCF客户端调用服务

    1.创建WCF客户端应用程序需要执行下列步骤 (1).获取服务终结点的服务协定.绑定以及地址信息 (2).使用该信息创建WCF客户端 (3).调用操作 (4).关闭WCF客户端对象 二.操作实例 1. ...

  6. WCF系列(一)BasicHttpBinding 和 WsHttpBinding 的不同点

    aaaaaaaaaaaaaaaaaa WCF系列(一)[翻译]BasicHttpBinding 和 WsHttpBinding 的不同点 2010-02-21 12:23 by Virus-Beaut ...

  7. WCF系列_分布式事务(下)

    1. WCF分布式事务例子 这里也用转账的例子说事. 用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B的相应账户的资金就增加多少. 系统A机器上有数据库AccountA ...

  8. IT-标准化-系列-15.在VPC 2007中构建虚拟网络

    看过太多人使用VPC 看过太多人使用Microsoft (R) Virtual Server 2005 R2 看过太多人使用VMware Workstation 没见过有人你像我这样夸张过! 为构建虚 ...

  9. 【干货】美团大脑系列之商品知识图谱的构建及应用.pdf(附下载链接)

    今天给大家带来美团AI平台搜索与NLP部曹雪智先生所做的分享<美团大脑系列之商品知识图谱的构建及应用.pdf>,关注美团大脑及知识图谱的伙伴们别错过了.本次分享包含如下四大部分: 1.美团 ...

最新文章

  1. python迭代器高级例子
  2. 20145305 《Java程序设计》第7周学习总结
  3. Apache 重写规则的常见应用 (rewrite)
  4. python with关键字_完全理解Python关键字with与上下文管理器
  5. SQLLite数据库操作
  6. cp oracle,Oracle ASM使用asmcmd中的cp命令来执行远程复制
  7. else列表推导式 if python_python3基础09列表推导式|迭代器|生成器|匿名函数
  8. 我们要有把坏事看成好事的能力
  9. [HDU3683 Gomoku]
  10. 魔抓编程_编程中的魔数是什么?
  11. c++经典小游戏,源码奉上(免费复制)
  12. windows media 服务器运行失败,Windows Media Player出现服务器运行失败怎么办?出现服务器运行失败处理方法介绍...
  13. 企业微信调试H5页面
  14. docker 安装snipe-it
  15. 从中序和前序遍历序列构造二叉树
  16. 安全月报| PeckShield:9月共发生安全事件14起,损失近1,800万美元
  17. 【中医学】0 绪论 + 1 阴阳五行学说
  18. 循环辅助:continue
  19. JeecgBoot 2.4.6 版本发布,基于代码生成器的企业级低代码平台
  20. 【笔记】编程的原则:改善代码质量的101个方法

热门文章

  1. Java DecimalFormat 用法 小数位的处理 公司内部处理小数位
  2. matlab怎么输入输出文件,[转载]底层文件输入输出函数
  3. java函数定义的要素_Java学习笔记八(方法)
  4. python动态网页开发教程_python django创建一个属于自己的动态网站
  5. matlab怎么调用DeepLearn,使用DeepLearnToolbox-master中DBN工具箱做数据分类出现问题,求......
  6. 信号与系统2021年期末考试命题
  7. Apache Commons包 StringUtils工具类深入整理(转载)
  8. java包装类和基本类型谁先谁后_你知道Java中基本类型和包装类的区别吗
  9. 生命周期共有那几个阶段_一文搞懂ReactNative生命周期的进化
  10. java gson 工具类_gson工具类将Java类转换为json的使用