绛河 初识WCF5

然后我们在<Client>中添加一个终结点,这个是客户端的终结点,我们前面曾经提过,通信实际上发生在两个终结点间,客户端也有个终结点,然而请求总是从客户端首先发起,所以终结点地址应该填写为服务端终结点的地址让客户端来寻址,但是服务协定要客户端本地是有的,所以这个要写本地定义的那个协定的完全限定名:

 

引用http://blog.csdn.net/songyefei/article/details/7389186

第五篇 再探通信--ClientBase

 

在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创建了通道,实现了和服务端的通信。然而,与服务端通信的编程模型不只一种,今天我们来学习利用另外一个服务类ClientBase<>来完成同样的工作,了解了这个类的使用方法,我们对服务引用中的关键部分就能够理解了。

 

 

 

ClientBase<>类也是一个泛型类,接受服务协定作为泛型参数,与ChannelFactory<>不同的是,这个类是一个基类,即抽象类,是不能实例化成对象直接使用的,我们需要自己写一个类来继承这个类,我们新写的类实例化出来就是客户端代理了,这个对象可以调用基类的一些受保护的方法来实现通信。ClientBase<>为我们封装的很好,我们只需要写个新类来继承他就可以了,通信的很多部分他都替我们做好了,比如我们不用进行去创建通道和打开通道的操作,直接调用协定方法就可以了。这也是服务引用和其他元数据生成工具(如svcutil)使用这个类来构造客户端代理的原因。

 

 

 

我们一边动手一边学习

 

 

 

1. 建立客户端程序

 

我们依然不用服务引用,完全手写,这次还是建立一个控制台应用程序作为客户端。

 

2. 添加必要的引用

 

我们用到的ClientBase<>类在System.ServiceModel程序集中,因此,要添加这个程序集的引用,同时在program.cs中添加using语句

    1. using System.ServiceModel; 

这一步应该很熟了,如果有疑问,返回前几篇温习一下。

因为没有使用服务引用,客户端现在没有任何元数据的信息,我们要来手写。首先把服务协定写进去。这个再熟悉不过了(写在Program类后面):

    [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  

4. 编写客户端代理类

上面已经提到,我们要自己写一个新类来继承ClientBase<>基类,这样这个新类就是代理类了,同时,为了能够用代理类直接调用服务协定的方法,我们还要让代理类实现服务协定的接口,注意,继承要写在前面,实现接口要写在后面。我们把这个类起名为HelloWCFClient。

    public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {   }  

ClientBase<>有许多的构造函数,接受不同种类的参数来创建代理类对象,其实这些参数都是元数据信息,刚才我们已经通过泛型参数传递给基类服务协定这个元数据了,现在基类还需要绑定和终结点地址这两个元数据才能正确创建连接,所以我们继承的新类应该把这个构造函数给覆载一下接受这两种元数据参数并传递给基类。

public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  
{  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  
} 

我们看到这个新建的构造函数什么也没做,只是接受了两个参数,一个是绑定,一个是终结点地址,然后直接调用基类(也就是ClientBase<>)的构造函数,把这个两个参数传递了上去。其实工作都是ClientBase<>做的,我们新建的类就是个传话的,要不然怎么叫代理呢,他什么活都不干。

既然我们实现了服务协定接口,当然要实现接口的方法了。下面我们把方法的实现写下来:

public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  
{  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  
} 

别忘了你的处境,凡人!我们这是在客户端啊,怎么可能有服务协定呢?这个可以有,但是这个实现不是我们在做,而是要和服务端通信让服务端做,这里可以看到代理鲜明的特点了,代理类虽然实现了服务协定的方法,但是在方法中,他调用了基类(就是ClientBase<>)上的通道,并通过通道调用了了协定方法。此时,ClientBase<>已经为我们建立好与服务端的通道了,而且是用服务协定建立的,我们当然可以在通道上调用服务协定的方法。所以调用代理类对象的HelloWCF()的过程是代理类委托基类在已经建立好的服务协定通道上调用协定方法,并从服务端获得返回值,然后再返回给代理类对象的调用者。狗腿啊狗腿。

5. 编写程序主体

代理类已经写完了,我们现在开始写程序的主体,让我们来到Program的Main函数中。

还是有一些准备要做,还差两个元数据呢,对了,就是绑定和地址。和上一篇一样,我们先建立这个两个元数据的对象备用:

    WSHttpBinding binding = new WSHttpBinding();  EndpointAddress remoteAddress = new EndpointAddress("http://localhost/IISService/HelloWCFService.svc");  

接下来就要建立我们的代理类对象了,new一个出来吧:

    HelloWCFClient client = new HelloWCFClient(binding, remoteAddress);  

把我们刚刚建立的两个元数据对象作为参数传递进去。

 

接下来就可以调用服务协定方法了:

string result = client.HelloWCF(); 


别忘了关闭通道,ClientBase<>很贴心的为我们准备了这个方法,不用再做强制类型转换什么的了(见前一篇)。

client.Close(); 

以下是Program.cs的全部代码:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  using System.ServiceModel;  namespace ConsoleClient  
{  class Program  {  static void Main(string[] args)  {  WSHttpBinding binding = new WSHttpBinding();  EndpointAddress remoteAddress = new EndpointAddress("http://localhost/IISService/HelloWCFService.svc");  HelloWCFClient client = new HelloWCFClient(binding, remoteAddress);  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  }  [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  }  
} 

6. 再展开一点点

这样看上去已经挺成功了,我们现在再打开服务引用的reference.cs代码,看看是不是大部分都看得懂了?监管有些地方他写的可能有些复杂,比如描述协定的属性参数啊,代理类更多的构造函数啊,但是核心的就是我们刚刚写的部分,那一大堆wsdl什么的其实都不是核心,不信的话你把他们都删掉,就留一个reference.cs看看还好不好用?那一堆东西也不是没用就是现在自己看起来还蛮复杂的,我们到后面一点点学习。

 

我们仔细看服务引用的reference.cs代码,有一样东西是我们有而他没有的,那就是对终结点地址和绑定的建立,而且在使用服务引用的时候我们也没有提供之两样东西,直接掉服务协定方法就行了(见第一篇),那么服务引用是从哪里找到这两个关键的元数据元素呢?

 

就在配置文件里,我们做的客户端还没有配置文件,我们可以把这两个元素都放在配置文件里,这样就可以避免硬编码了。

 

为我们的控制台应用程序添加一个应用程序配置文件。方法是右键点击项目->添加->新建项->应用程序配置文件。保持默认名称app.config。

打开来看,里面没写什么实际的内容:

    <?xml version="1.0" encoding="utf-8" ?>  <configuration>  </configuration>  

我们对配置服务应该不陌生,如果忘记了,翻回到第二篇去回顾一下。

首先还是要添加<System.ServiceModel>节,无论是服务端还是客户端,只要是WCF的服务配置都要在这个节里面:

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  <system.serviceModel>  </system.serviceModel>  
</configuration> 

在这里我们要配置的是客户端,所以我们不添加<Services>节了,而改成<Client>:

    <?xml version="1.0" encoding="utf-8" ?>  <configuration>  <system.serviceModel>  <client>  </client>  </system.serviceModel>  </configuration>  

 

如果你忘记了我们在第三篇中配置的IIS服务的内容,可能稍有迷惑,这里的地址看上去是个服务地址而不是终结点地址,这是因为我们在IIS中把终结点地址设置为了空字符串,此时服务地址就是终结点地址了。注意看后面的contract,他的完全限定名的命名空间是客户端程序的命名空间ConsoleClient,这也表示这个类型是定义在本地的,不要搞错了。

 

保存,配置已经写完了,你如果看服务引用为我们生成的配置会看到一堆东西,实际上核心的就是这些。

 

既然我们已经在配置中声明了绑定和终结点地址,在代码中就不再需要了。

首先我们修改一下代理类,为他提供一个没有参数的构造函数,否则在new他的时候他会非管我们要两个参数。

public HelloWCFClient()  : base()  
{   } 

还是什么也不做,直接调基类的无参构造函数。

 

然后修改一下Main函数,去掉终结点对象和地址对象的声明,并用无参构造函数来new 代理类的实例:

    static void Main(string[] args)  {  HelloWCFClient client = new HelloWCFClient();  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  

F5运行一下,结果如一吧!

到这里已经和服务引用的感觉基本一样了,我们已经写出了服务引用的核心部分。

以下是修改后的Program.cs完整代码:

    using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.ServiceModel;  namespace ConsoleClient  {  class Program  {  static void Main(string[] args)  {  HelloWCFClient client = new HelloWCFClient();  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  }  [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {  public HelloWCFClient()  : base()  {   }  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  }  }  

7. 总结

通过本篇的学习,我们熟悉了另一种与服务端通信的办法,即通过ClientBase<>派生代理类的方法,这种方法实际上就是服务引用使用的方法,可以说我们已经在最简单级别上手写了一个服务引用的实现。

 

使用ChannelFactory<>和ClientBase<>都可以实现与服务端的通信,这是类库支持的最高层次的通讯方法了,其实还有更底层的通道通信方法,我们现在就不再深入了。而选择这两种方法完全取决于开发人员,有人喜欢工厂,有人喜欢代理类。既然我们都已经掌握了,就随意选择吧。

 

至此,我们对通信有了一个基本的了解,只能算一个初探吧。然而我相信这一次的小小深入会对我们今后的学习带来大大的帮助的。

 

转载于:https://www.cnblogs.com/janghe/p/7594217.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python修炼第四天

今天换了师傅。江湖人称景女神^o^。 女师傅讲的比较细&#xff0c;原理的比较多。初学者来说有些难。但是基本功是必须要打牢的。努力&#xff01; 迭代器 迭代器&#xff0c;迭代的工具1 什么是迭代&#xff0c;指的是一个重复的过程&#xff0c;每一次重复称为一次迭代&#…

尴尬的存储过程

最近在给一个已沉淀了多年的系统框架进行优化&#xff0c;发现大部分的基础业务&#xff08;比如增删改&#xff09;的实现都是通过存储过程来实现。这让我纠结了很久&#xff0c;看了下代码格式我猜应该都是使用了代码生成器。这无疑为系统的扩展留下了一个难以弥补的大坑。 首…

java虚拟机06-内存分区/新生代、老年代

1.原因 JVM在程序运行过程当中&#xff0c;会创建大量的对象&#xff0c;这些对象&#xff0c;大部分是短周期的对象&#xff0c;小部分是长周期的对象&#xff0c;对于短周期的对象&#xff0c;需要频繁地进行垃圾回收以保证无用对象尽早被释放掉&#xff0c;对于长周期对象&a…

博客作业04--树

1.学习总结(2分) 1.1树结构思维导图 1.2 树结构学习体会 树这一章节比较复杂&#xff0c;知识点繁多&#xff0c;结合了递归的知识所以代码阅读起来会有障碍&#xff0c;难以理解&#xff0c;所以学起来比较吃力&#xff0c;而且很多经典的算法理解的不是很透彻解决pta上的问题…

Centos 配置多个虚拟IP

Centos 配置多个虚拟IP 临时设置 ifconfig enp2s0:3 192.168.3.152 netmask 255.255.255.0 up 复制代码永久生效 TYPEEthernet BOOTPROTOnone NAMEenp2s0 DEVICEenp2s0 HWADDR40:8d:5c:bc:f4:d8 ONBOOTyes IPADDR0192.168.3.200 PREFIX024 GATEWAY0192.168.3.254 IPADDR1192.16…

[转]MySQL日志——Undo | Redo

本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo LogUndo Log 是为了实现事务的原子性&#xff0c;在MySQL数据库InnoDB存储引擎中&#xff0c;还用Undo Log来实现多版本并发控制(简称&#xff1a;MVCC)。 - 事务的原子性(Atomicity) 事务中的所有操作&#xff0…

Vim操作指南

vim具有6种基本模式和5种派生模式。 基本模式 普通模式 插入模式 可视模式 选择模式 命令行模式 Ex模式 派生模式 操作符等待模式 插入普通模式 插入可视模式 插入选择模式 替换模式 1.移动光标&#xff08;普通模式下&#xff09; h&#xff1a;左 j&#xff1a;下 …

[DP/单调队列]BZOJ 2059 [Usaco2010 Nov]Buying Feed 购买饲料

首先我想吐槽的是题目并没有表明数据范围。。。 这个题目 DP方程并不难表示。 dp[i][j]表示前i个地点携带了j个货物的最小花费 dp[i][j] dp[i-1][k] (j-k) * cost j*j*(leng[i]-leng[i-1]) 如果你这样直接提交上去&#xff0c;恭喜你超时&#xff01;&#xff01;&#xff0…

十天冲刺09

今天&#xff0c;和小伙伴在做密保功能的开发&#xff0c;而且通过密保可以找回用户密码。转载于:https://www.cnblogs.com/Excusezuo/p/10923690.html

hdu 6168 Numbers

zk has n numbers a1,a2,...,an. For each (i,j) satisfying 1≤i<j≤n, zk generates a new number (aiaj). These new numbers could make up a new sequence b1&#xff0c;b2,...,bn(n−1)/2 . LsF wants to make some trouble. While zk is sleeping, Lsf mixed up seq…

039_MySQL_多表查询

#创建部门 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment PRIMARY KEY,dname VARCHAR(50) not null COMMENT 部门名称 )ENGINEINNODB DEFAULT charset utf8;#添加部门数据 INSERT INTO dept VALUES (1, 教学部); INSERT INTO dept VALUES (2, 销售部); IN…

sqlserver 创建对某个存储过程执行情况的跟踪

有时候需要抓取执行存储过程时某个参数的值&#xff0c;有时候程序调用存储过程执行后结果不太对&#xff0c;不确定是程序的问题还是存储过程的问题&#xff0c;需要单独执行存储过程看结果 即可用下面的方法 -- --创建对某个存储过程的执行情况的跟踪 --注意修改路径 和 obje…

5.7 弹性盒子

弹性盒子定义弹性盒子 display&#xff1a;flex定义子元素排列方式 flex-diection定义子元素换行方式 flxe-wrap定义子元素对齐方式横向对齐 justify-content纵向对齐 align-items 媒体查询 media screen and (max-width:最大宽度)and &#xff08;min-width&#xff1a;最小…

4.navicat11激活教程,亲测可用哦!

原文地址&#xff1a;http://blog.csdn.net/sanbingyutuoniao123/article/details/52589678Navicat是一款数据库管理工具, 用于简化, 开发和管理MySQL, SQL Server, SQLite, Oracle 和 PostgreSQL 的数据库&#xff1b;Navicat数据模型工具以图形化方式创建关联式数据库&#x…

汉诺塔问题深度剖析(python实现)

当我们学习一门编程语言的时候&#xff0c;都会遇到递归函数这个问题。而学习递归的一个经典案例就是汉诺塔问题。通过这篇文章&#xff0c;观察移动三个盘子和四个盘子的详细过程&#xff0c;您不仅可以深刻的了解递归&#xff0c;也更加熟悉了汉诺塔的游戏的玩法。 更好的阅读…

iOS-QQ临时对话、QQ群申请跳转

QQ 临时对话 NSString *qq [NSString stringWithFormat:"mqq://im/chat?chat_typewpa&uin%&&version1&src_typeweb","这是是QQ号码"];NSURL *urlQQ [NSURL URLWithString:qq];[[UIApplication sharedApplication] openURL:urlQQ]; QQ 申…

[luoguP2331] [SCOI2005]最大子矩阵(DP)

传送门 orz不会做。。。 一个好理解的做法&#xff08;n^3*k&#xff09;&#xff1a; 分n1和n2两种情况考虑。 n1时&#xff0c;预处理出前缀和sum[]。 设f[i][j]为到达第i格&#xff0c;已经放了j个子矩阵的最大和&#xff0c; 那么每次先把f[i][j]的值设为f[i-1][j]&#xf…

想要去阿里面试?你必须得跨过 JVM 这道坎!

概述 很多人想要到阿里巴巴、美团、京东等互联网大公司去面试&#xff0c;但是现在互联网大厂面试一般都必定会考核JVM相关的知识积累和实践经验&#xff0c;毕竟线上系统写好代码部署之后&#xff0c;每个工程师都必须关注JVM相关的东西&#xff0c;比如OOM、GC等问题. 所以一…

医学知识图谱一

大纲 知识自动提取技术 医学知识融合 医学知识推理 转载于:https://www.cnblogs.com/quietwalk/p/9000950.html

在一个div里,列表样式图片进行float,实现水平排序

<div class"xiangce"><ul> <li><a href"#"><img src"images/pic4.gif" alt"">产品名称</a></li><li><a href"#"><img src"images/pic4.gif" alt"…