1.WCF学习--创建简单的WCF服务
一、基本了解WCF
1、面向服务代表的是一种设计理念,和面向对象、面向组件一样,体现的是一种对关注点进行分解的思想,面向服务是和技术无关的
2、WCF需要依存一个运行着的宿主进程,服务寄宿就是为服务指定一个宿主的过程,服务寄宿的目的就是开启一个进程,为WCF提供一个运行的环境,并为服务提供一个或多个终结点,使之暴露给潜在的服务消费者
WCF采用基于终结点(Endpoint)的通信手段。终结点由地址(Address)、绑定(Binding)、契约(Contract)三要数组成
地址:地址决定了服务的位置,解决了服务寻址的问题
绑定:绑定实现了通讯所有细节,包括网络传输、消息编码、以及其他为实现某种功能(比如传输安全、可靠消息、事务等)对消息进行相应的处理。
契约:契约是对服务操作的抽象,也是对消息交换及消息结构的定义
注意:WCF中具有一系列的系统定义绑定,比如:BasicHttpBinding、WSHttpBinding和NetTcpBinding等
二、构建简单的WCF应用
目录结构如下:
Service.Interface:用于定义服务契约的类库项目,引用WCF核心程序集 System.ServiceModel.dll
Service:用于定义服务类型的类库项目,实现服务契约(Service.Interface)
Hosting:作为服务寄宿的控制台应用
WCF_自我寄宿:客户端,调用服务
定义服务契约:
/// <summary>
/// 用于定义服务契约的地方Contract
/// </summary>
namespace Service.Interface
{
/// <summary>
/// 当服务被添加到客户端程序时,契约接口会被生成出来,出来的名称与 ServiceContract特性里面属性name定义的名称一样
/// </summary>
[ServiceContract(Name ="CalculatorService",Namespace ="http://www.artech.com/")]
public interface ICalculator
{
[OperationContract]
double Add(double x, double y); [OperationContract]
double Subtract(double x, double y); [OperationContract]
double Multiply(double x, double y); [OperationContract]
double Divide(double x, double y);
}
}
使用编程方式寄宿:
/// <summary>
/// 使用编程方式寄宿
/// </summary>
public static void Programme()
{
//服务寄宿
using (ServiceHost host = new ServiceHost(typeof(Service.CalculatorService)))
{
//添加终结点(一个基于WSHttpBinding绑定的终结点 终结点地址:http://127.0.0.1:3721/calculatorservice 服务契约的类型:ICalculator)
host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice");
if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
// 添加服务行为(控制服务元数据和相关信息的发布。)
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;//指定采用http-get的元数据获取方式
behavior.HttpGetUrl = new Uri("http://127.0.0.1:3721/calculatorservice/metadata");//指定元数据发布地址,这样在服务寄宿后我们可以通过这个地址访问服务相关的元数据
host.Description.Behaviors.Add(behavior);
} host.Opened += delegate
{
Console.WriteLine("CalculatorService 启动,按任意键终止服务!");
};
host.Open();//开启服务
Console.Read();
}
}
使用配置文件寄宿
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadateBehavior">
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
<serviceMetadata httpGetEnabled="true" httpGetUrl="calculatorservice/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadateBehavior" name="Service.CalculatorService">
<endpoint address="calculatorservice" binding="wsHttpBinding"
name="Service.CalculatorService" contract="Service.Interface.ICalculator" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:3721" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
/// <summary>
/// 使用配置文件添加服务
/// </summary>
public static void Config()
{
using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
host.Opened += delegate
{
Console.WriteLine("CalculatorService 启动,按任意键终止服务!");
};
host.Open();//开启服务
Console.Read();
}
}
客户端调用服务:
1、当服务被添加后,客户端进行服务调用的服务契约接口CalculatorService会被生成出来并且与ICalculator契约接口具有相同的成员且等效
注意:这个掉用的服务契约与定义契约接口时使用ServiceContractAttribute特性的name属性设置的一样
namespace WCF_自我寄宿.ServiceReference1 { [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.artech.com/", ConfigurationName="ServiceReference1.CalculatorService")]
public interface CalculatorService { [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Add", ReplyAction="http://www.artech.com/CalculatorService/AddResponse")]
double Add(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Add", ReplyAction="http://www.artech.com/CalculatorService/AddResponse")]
System.Threading.Tasks.Task<double> AddAsync(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Subtract", ReplyAction="http://www.artech.com/CalculatorService/SubtractResponse")]
double Subtract(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Subtract", ReplyAction="http://www.artech.com/CalculatorService/SubtractResponse")]
System.Threading.Tasks.Task<double> SubtractAsync(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Multiply", ReplyAction="http://www.artech.com/CalculatorService/MultiplyResponse")]
double Multiply(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Multiply", ReplyAction="http://www.artech.com/CalculatorService/MultiplyResponse")]
System.Threading.Tasks.Task<double> MultiplyAsync(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Divide", ReplyAction="http://www.artech.com/CalculatorService/DivideResponse")]
double Divide(double x, double y); [System.ServiceModel.OperationContractAttribute(Action="http://www.artech.com/CalculatorService/Divide", ReplyAction="http://www.artech.com/CalculatorService/DivideResponse")]
System.Threading.Tasks.Task<double> DivideAsync(double x, double y);
} [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface CalculatorServiceChannel : WCF_自我寄宿.ServiceReference1.CalculatorService, System.ServiceModel.IClientChannel {
} [System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>, WCF_自我寄宿.ServiceReference1.CalculatorService { public CalculatorServiceClient() {
} public CalculatorServiceClient(string endpointConfigurationName) :
base(endpointConfigurationName) {
} public CalculatorServiceClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
} public CalculatorServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
} public CalculatorServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
} public double Add(double x, double y) {
return base.Channel.Add(x, y);
} public System.Threading.Tasks.Task<double> AddAsync(double x, double y) {
return base.Channel.AddAsync(x, y);
} public double Subtract(double x, double y) {
return base.Channel.Subtract(x, y);
} public System.Threading.Tasks.Task<double> SubtractAsync(double x, double y) {
return base.Channel.SubtractAsync(x, y);
} public double Multiply(double x, double y) {
return base.Channel.Multiply(x, y);
} public System.Threading.Tasks.Task<double> MultiplyAsync(double x, double y) {
return base.Channel.MultiplyAsync(x, y);
} public double Divide(double x, double y) {
return base.Channel.Divide(x, y);
} public System.Threading.Tasks.Task<double> DivideAsync(double x, double y) {
return base.Channel.DivideAsync(x, y);
}
}
}
2、查看调用服务后生成的代码可以看出来其实真正被调用的是CalculatorServiceClient类
public interface CalculatorService
public partial class CalculatorServiceClient : System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>, WCF_自我寄宿.ServiceReference1.CalculatorService
可以看到CalculatorServiceClient同样实现了契约接口并且其基类是System.ServiceModel.ClientBase<WCF_自我寄宿.ServiceReference1.CalculatorService>,
并通过从基类继承的Channel属性的相应方法实现了4个运算操作
客户端引用服务后字节调用:
//1、直接调用
CalculatorServiceClient client = new CalculatorServiceClient();
Console.WriteLine(client.Add(, ));
由于WCF采用基于契约的服务调用方法。
vs在添加服务的时候会在客户端创建一个与服务等效的服务契约接口。 public interface CalculatorService
由于服务端和客户端在同一个解决方案里面,因此可以让服务端和客户端引用相同的契约(当然这里是删除了服务引用,并且引用服务契约1Calculator)
通过System.ServiceModel.ChannelFactory<Tchannel>直接创建服务代理对象
using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice"))
{
ICalculator calculator = channelFactory.CreateChannel();
Console.WriteLine(calculator.Add(, ));
}
说明:
终结点是WCF进行通讯的唯一手段,ChannelFactory<ICalculator>本质上是通过指定的终结点创建用于进行服务调用的服务代理
在创建channelFactory对象的时候我们指定了 地址和绑定 泛型ChannelFactory<ICalculator>指定了 契约
一般我们通过在配置文件添加终结点(常用)再通过System.ServiceModel.ChannelFactory<Tchannel>直接创建服务代理对象
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<client>
<endpoint
address="http://127.0.0.1:3721/calculatorservice"
binding="wsHttpBinding"
contract="Service.Interface.ICalculator"
name="CalCulatorService" />
</client>
</system.serviceModel>
</configuration>
using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("CalCulatorService"))
{
ICalculator calculator = channelFactory.CreateChannel();
Console.WriteLine(calculator.Add(, ));
Console.WriteLine("按任意键终止程序");
Console.Read();
}
IIS寄宿:https://blog.csdn.net/heyangyi_19940703/article/details/51831094
1.WCF学习--创建简单的WCF服务的更多相关文章
- WCF学习心得----(四)服务承载
WCF学习心得----(四)服务承载 这一章节花费了好长的时间才整理个大概,主要原因是初次接触这个东西,在做练习实践的过程中,遇到了很多的问题,有些问题到目前还没有得以解决.所以在这一章节中,有一个承 ...
- WCF学习心得----(三)服务承载
WCF学习心得----(三)服务承载 这一章节花费了好长的时间才整理个大概,主要原因是初次接触这个东西,在做练习实践的过程中,遇到了很多的问题,有些问题到目前还没有得以解决.所以在这一章节中,有一个承 ...
- [WCF学习笔记] 我的WCF之旅(1):创建一个简单的WCF程序
近日学习WCF,找了很多资料,终于找到了Artech这个不错的系列.希望能从中有所收获. 本文用于记录在学习和实践WCF过程中遇到的各种基础问题以及解决方法,以供日后回顾翻阅.可能这些问题都很基础,可 ...
- WCF学习之旅—实现REST服务(二十二)
一.什么是REST 表述性状态转移(Representational State Transfer,REST),不是一种标准,而是一种软件架构风格. 基于REST的服务与基于SOAP的服务相比,性能. ...
- [WCF REST] 一个简单的REST服务实例
Get:http://www.cnblogs.com/artech/archive/2012/02/04/wcf-rest-sample.html [01] 一个简单的REST服务实例 [02] We ...
- WCF学习笔记(1)——Hello WCF
1.什么是WCF Windows Communication Foundation(WCF)是一个面向服务(SOA)的通讯框架,作为.NET Framework 3.0的重要组成部分于2006年正式发 ...
- WCF学习系列二---【WCF Interview Questions – Part 2 翻译系列】
http://www.topwcftutorials.net/2012/09/wcf-faqs-part2.html WCF Interview Questions – Part 2 This WCF ...
- WCF学习系列一【WCF Interview Questions-Part 1 翻译系列】
http://www.topwcftutorials.net/2012/08/wcf-faqs-part1.html WCF Interview Questions – Part 1 This WCF ...
- WCF学习系列三--【WCF Interview Questions – Part 3 翻译系列】
http://www.topwcftutorials.net/2012/10/wcf-faqs-part3.html WCF Interview Questions – Part 3 This WCF ...
随机推荐
- sqlserver安装-1
原文地址: https://blog.csdn.net/qq_41432123/article/details/79053486 下载:(免费使用安装dev版) ed2k://|file|cn_sql ...
- LLDB动态调试
- Vue通信、传值的多种方式,详解(都是干货)
Vue通信.传值的多种方式,详解(都是干货) 可参考博客: https://blog.csdn.net/qq_35430000/article/details/79291287
- Mybatis入门之MyBatis项目案例
一.项目案例演示 后台管理系统用户数据维护平台 所有用户数据查询 单个用户数据查询 用户数据修改(完善资料) 锁定用户账号 删除用户账号 彻底删除用户账号 二.数据库数据准备工作 数据库:mysql ...
- 备份mysql的shell
• #!/bin/bash• file_name=`date +%Y%m%d%H%M%S`• db_path='/usr/local/db_back/'• mysqldump -ulepus -p12 ...
- vue搭建项目之设置代理
前面将项目页面.axios.组件等都准备好了,现在就差设置代理了: 首先在config下新建两个文件,分别叫做dev.uri.js和prod.uri.js,代码为: module.exports = ...
- KEIL建立新唐MCU的工程时,移植官网程序报错变量未定义问题解决方法
最近在使用新唐的MCU,新唐的MCU使用还算方便,你安装好KEIL之后再安装 Nu-Link_Keil_Driver_V3.00.6909 驱动即可建立新唐的MCU工程,注意的是因为新唐MCU是C51 ...
- Vagrant 入门 - 清理(teardown)
原文地址 我们现在有一个功能齐全的虚拟机,可以用于基本 Web 开发.但如果现在需要更换设备,或者在另一个项目上工作,如何清理我们的开发环境? 借助 Vagrant,可以暂停(suspend),停止( ...
- JSP基础--动作标签
JSP动作标签 1 JSP动作标签概述 动作标签的作用是用来简化Java脚本的! JSP动作标签是JavaWeb内置的动作标签,它们是已经定义好的动作标签,我们可以拿来直接使用. 如果JSP动作标签不 ...
- Day5---Python的random库
random库 1.random库是随机数的Python标准库 2.原理 : random生成的伪随机数,而采用梅森旋转算法生成的(伪)随机序列中的元素叫做伪随机数 https://liam.pa ...