【WCF--初入江湖】01 WCF编程概述
01 WCF编程概述
SOA的优点
什么是WCF
WCF
是微软分布式应用程序开发的集大成者,它整合了.Net平台下所有的和分布式系统有关的技术,如
Enterprise Sevices
(COM+).Net Remoting(一种非常有弹性的扩展性框架)、
Web Service(ASMX)、
WSE3.0
MSMQ消息队列。
以通信(Communiation)范围而论,它可以
跨进程、跨机器、跨子网、企业网乃至于 Internet;
以宿主程序而论,可以以
ASP.NET,EXE,WPF,Windows Forms,NT Service,COM+作为宿主(Host)
WCF可以支持的协议包括TCP,
HTTP,跨进程以及自定义,
安全模式则包括SAML, Kerberos,X509,用户/密码,
自定义等多种标准与模式。
也就是说,在WCF框架下,开发基于SOA的分布式系统变得容易了,微软将所有与此相关的技术要素都包含在内,掌握了WCF,就相当于掌握了叩开SOA大门的钥匙
WCF与webService是什么关系
ASP.NET Web Service:
利用Soap协议对象在分布式环境之间的数据交互。
WSDL来发布服务接口相关的描写。
称为WSE系列:
ASP.NET Web Service的安全,功能,数据加密、解密,托管宿主等多方面的伸展,
WCF宿主
static void Main(string[] args)
{
var baseAddress = ConfigurationManager.AppSettings["baseAddress"];
ApplicationService.Initialize();
MongoDBBootstrapper.Bootstrap(); using (ServiceHost orderService = new ServiceHost(typeof(OrderService), new Uri(string.Format("{0}/OrderService.svc", baseAddress))))
using (ServiceHost productService = new ServiceHost(typeof(ProductService), new Uri(string.Format("{0}/ProductService.svc", baseAddress))))
using (ServiceHost userService = new ServiceHost(typeof(UserService), new Uri(string.Format("{0}/UserService.svc", baseAddress))))
{
orderService.Open();
productService.Open();
userService.Open(); Console.WriteLine("Byteart Retail Services started at: {0}.", DateTime.Now);
Console.ReadLine();
Console.WriteLine("Byteart Retail Services stopped at: {0}.", DateTime.Now); orderService.Close();
productService.Close();
userService.Close();
}
}
<appSettings>
<add key="baseAddress" value="http://localhost:8559"/>
</appSettings>
服务端配置:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="unity" type="ByteartRetail.Infrastructure.UnityExtensions.UnityBehaviorExtensionElement, ByteartRetail.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<unity operationContextEnabled="true" instanceContextEnabled="true" contextChannelEnabled="true" serviceHostBaseEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
另一种配置,
namespace Keasy5.WCF.WCFHost
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost serviceHostPerCall = new ServiceHost(typeof(ServicePerCall)))
using (ServiceHost serviceHostPerSession = new ServiceHost(typeof(ServicePerSession)))
using (ServiceHost serviceHostSingle = new ServiceHost(typeof(ServiceSingle)))
{
serviceHostPerCall.Open();
serviceHostPerSession.Open();
serviceHostSingle.Open(); Console.WriteLine("所有服务已经启动: {0}.", DateTime.Now);
Console.ReadLine();
Console.WriteLine("所有服务已经关闭: {0}.", DateTime.Now); serviceHostPerCall.Close();
serviceHostPerSession.Close();
serviceHostSingle.Close();
}
}
}
}
对应的配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration> <system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="Keasy5.WCF.WCFService.ServicePerCall" behaviorConfiguration="textserviceBehaviors">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:5833/Keasy5.WCF.WCFService/ServicePerCall/" />
</baseAddresses>
</host>
<endpoint name="ServicePerCall" address="" binding="basicHttpBinding" contract="Keasy5.WCF.WCFService.IService1"></endpoint>
</service> <service name="Keasy5.WCF.WCFService.ServicePerSession" behaviorConfiguration="textserviceBehaviors">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:5833/Keasy5.WCF.WCFService/ServicePerSession/" />
</baseAddresses>
</host>
<endpoint name="" address="" binding="basicHttpBinding" contract="Keasy5.WCF.WCFService.IService1"></endpoint>
</service> <service name="Keasy5.WCF.WCFService.ServiceSingle" behaviorConfiguration="textserviceBehaviors">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:5833/Keasy5.WCF.WCFService/ServiceSingle/" />
</baseAddresses>
</host>
<endpoint name="ServiceSingle" address="" binding="basicHttpBinding" contract="Keasy5.WCF.WCFService.IService1"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors >
<behavior name="textserviceBehaviors">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> </configuration>
客户端调用
获取WCF服务的一个封装类:
ServiceProxy.cs
using System.ServiceModel; namespace ByteartRetail.Infrastructure.Communication
{
/// <summary>
/// 表示用于调用WCF服务的客户端服务代理类型。
/// </summary>
/// <typeparam name="T">需要调用的服务契约类型。</typeparam>
public sealed class ServiceProxy<T> : DisposableObject
where T : class, IApplicationServiceContract
{
#region Private Fields
private T client = null;
private static readonly object sync = new object();
#endregion #region Protected Methods
protected override void Dispose(bool disposing)
{
if (disposing)
lock (sync)
{
Close();
}
}
#endregion #region Public Properties
/// <summary>
/// 获取调用WCF服务的通道。
/// </summary>
public T Channel
{
get
{
lock (sync)
{
if (client != null)
{
var state = (client as IClientChannel).State;
if (state == CommunicationState.Closed)
client = null;
else
return client;
}
var factory = ChannelFactoryManager.Instance.GetFactory<T>();
client = factory.CreateChannel();
(client as IClientChannel).Open();
return client;
}
}
}
#endregion #region Public Methods
/// <summary>
/// 关闭并断开客户端通道(Client Channel)。
/// </summary>
/// <remarks>
/// 如果使用using语句对ServiceProxy进行了包裹,那么当程序执行点离开using的
/// 覆盖范围时,Close方法会被自动调用,此时客户端无需显式调用Close方法。反之
/// 如果没有使用using语句,那么则需要显式调用Close方法。
/// </remarks>
public void Close()
{
if (client != null)
((IClientChannel)client).Close();
}
#endregion
}
}
ChannelFactoryManager.cs
using System;
using System.Collections.Generic;
using System.ServiceModel; namespace ByteartRetail.Infrastructure.Communication
{
/// <summary>
/// 表示Channel Factory管理器。
/// </summary>
internal sealed class ChannelFactoryManager : DisposableObject
{
#region Private Fields
private static readonly Dictionary<Type, ChannelFactory> factories = new Dictionary<Type, ChannelFactory>();
private static readonly object sync = new object();
private static readonly ChannelFactoryManager instance = new ChannelFactoryManager();
#endregion #region Ctor
static ChannelFactoryManager() { }
private ChannelFactoryManager() { }
#endregion #region Public Properties
/// <summary>
/// 获取<c>ChannelFactoryManager</c>的单件(Singleton)实例。
/// </summary>
public static ChannelFactoryManager Instance
{
get { return instance; }
}
#endregion #region Protected Methods
protected override void Dispose(bool disposing)
{
if (disposing)
{
lock (sync)
{
foreach (Type type in factories.Keys)
{
ChannelFactory factory = factories[type];
try
{
factory.Close();
continue;
}
catch
{
factory.Abort();
continue;
}
}
factories.Clear();
}
}
}
#endregion #region Public Methods
/// <summary>
/// 获取与指定服务契约类型相关的Channel Factory实例。
/// </summary>
/// <typeparam name="T">服务契约的类型。</typeparam>
/// <returns>与指定服务契约类型相关的Channel Factory实例。</returns>
public ChannelFactory<T> GetFactory<T>()
where T : class, IApplicationServiceContract
{
lock (sync)
{
ChannelFactory factory = null;
if (!factories.TryGetValue(typeof(T), out factory))
{
factory = new ChannelFactory<T>(typeof(T).Name);
factory.Open();
factories.Add(typeof(T), factory);
}
return factory as ChannelFactory<T>;
}
}
#endregion
}
}
客户端调用:
using (ServiceProxy<IProductService> proxy = new ServiceProxy<IProductService>())
{
var categories = proxy.Channel.GetCategories(QuerySpec.Empty);
return View(categories);
}
客户端配置:
注意到ChannelFactoryManager类中创建工厂的方法:
public ChannelFactory<T> GetFactory<T>()
{
。。。。
factory = new ChannelFactory<T>(typeof(T).Name);
注意到ChannelFactoryManager类中创建工厂的方法,使用的是类型的名称typeof(T).Name)作为节点的配置名。
ChannelFactory<T>构造函数查看参数说明:
//
// 摘要:
// 使用指定的终结点配置名称初始化 System.ServiceModel.ChannelFactory<TChannel> 类的新实例。
//
// 参数:
// endpointConfigurationName:
// 用于终结点的配置名称。
//
// 异常:
// System.ArgumentNullException:
// endpointConfigurationName 为 null。
public ChannelFactory(string endpointConfigurationName);
故,客户端的配置EndPointd配置节点名要使用要用类型的名称,
<endpoint name="IProductService" 。。。
例如:
<endpoint name="IProductService" address="http://localhost:8558/ProductService.svc" contract="ByteartRetail.ServiceContracts.IProductService" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
客户端的配置:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ServiceProxyBinding" sendTimeout="00:10:00" receiveTimeout="00:10:00" closeTimeout="00:10:00" maxReceivedMessageSize="" maxBufferSize="">
<readerQuotas maxStringContentLength="" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="IProductService" address="http://localhost:8558/ProductService.svc" contract="ByteartRetail.ServiceContracts.IProductService" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
<endpoint name="IOrderService" address="http://localhost:8558/OrderService.svc" contract="ByteartRetail.ServiceContracts.IOrderService" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
<endpoint name="IUserService" address="http://localhost:8558/UserService.svc" contract="ByteartRetail.ServiceContracts.IUserService" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
<endpoint name="IPostbackService" address="http://localhost:8558/PostbackService.svc" contract="ByteartRetail.ServiceContracts.IPostbackService" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
</client>
</system.serviceModel>
【WCF--初入江湖】01 WCF编程概述的更多相关文章
- WCF 4.0 如何编程修改wcf配置,不使用web.config静态配置
How to programmatically modify WCF without web.config setting WCF 4.0 如何编程修改wcf配置,不使用web.config静态配置 ...
- WCF入门一[WCF概述]
一.什么是WCF WCF是使用托管代码建立和运行面向服务(Service Oriented)应用程序的统一框架.它使得开发者能够建立一个跨平台的.安全.可信赖.事务性的解决方案,且能与已有系统兼容协作 ...
- WCF入门三[WCF宿主]
一.概述 WCF程序必须在宿主上运行,也就是WCF服务必须寄宿在某一个windows的进程中,可以是IIS.控制台程序.窗体程序.WAS以及所有.net程序等程序进程中.在我用VS2013创建WCF服 ...
- WCF学习笔记——WCF基础
一 WCF与SOA SOA是一种通过为所有软件提供服务外观,并将这些服务的WSDL集中发布到一个地方的一种组织企业软件的方法.它通过使用明确定义的接口通过跨越边界传递消息来让多个自治的服务协同工作.S ...
- 第01章 Spring概述
第01章 Spring概述 1.Spring概述 ①Spring是一个开源框架 ②Spring为简化企业级开发而生,使用Spring,JavaBean就可以实现很多以前要靠EJB才能实现的功能.同样的 ...
- WCF服务与WCF数据服务的区别
问: Hi, I am newbie to wcf programming and a little bit confused between WCF Service and WCF Data Se ...
- Android网络编程概述
Android网络编程概述 首先,应该了解的几个问题: 1)Android平台网络相关API接口 a) java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流.数据包 ...
- [C#] 《Concurrency in C# Cookbook》读书笔记(一)- 并发编程概述
并发编程概述 前言 我们经常在耳边听说一些关于高性能.并发和并行等名词,并且很多人都对并发编程有一些误解. 误解 1:并发就是多线程? 答:多线程只不过是并发编程的其中一种形式而已.并发编程的种类很多 ...
- C# 图解教程 第二章 C#编程概述
C#编程概述 一个简单的C#程序标识符关键字Main:程序的起始点从程序输出文本注释 C#编程概述 一个简单的C#程序 标识符 标识符是一种字符串,用来命名变量.方法.参数和许多后面将要阐述的其他程序 ...
随机推荐
- AMQ学习笔记 - 15. 实践方案:基于ActiveMQ的统一日志服务
概述 以ActiveMQ + Log4j + Spring的技术组合,实现基于消息队列的统一日志服务. 参考:Spring+Log4j+ActiveMQ实现远程记录日志——实战+分析 与参考文章的比较 ...
- 7款纯CSS3实现的炫酷动画应用
1.纯CSS3实现人物摇头动画 这次我们要来分享一款超级可爱的纯CSS3人物摇头动画,初始化的时候人物的各个部位是利用CSS3动画效果拼接而成,接下来就是人物听音乐的场景,一边听音乐一边摇着脑袋,十分 ...
- C++ 中的 const 详解
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4235721.html 1.为什么使用 const int 而不使用 #define 在使用# ...
- linux 定时执行任务 crontab
欲编写定时任务访问网页和打开图片 原来写法为 #!/bin/bash #可以执行 echoecho "Hello" > dir/file.txt #不可以执行 xdg-ope ...
- jQuery: 图片不完全按比例自动缩小
有时我们会有这样的需求:让图片显示在固定大小的区域.如果不考虑 IE6 完全可以使用 css 的 max-width 限制宽度自动按比例缩小显示,但是这样有个问题,就是如果按比例缩小后,图片高度不够, ...
- DWZ前端框架使用问题记录
心得体验:DWZ依赖特定的HTML结构,所以一定要注意项目中的HTML结构,多用firebug查看,还有如果使用一些组件的时候出现问题,可以查看下返回JSON格式是否符合组件规定的JSON格式,很多都 ...
- 重拾C,一天一点点_4_随想
刚才顺便又把二分默写了一遍,还好,这次比较顺利.算法这一块,一直是自己一块痛处,有时感觉自己的脑瓜子怎么就这么笨,后一想觉得肯定是锈逗了,确实啊,这么长时间不思考的脑子能机灵到哪呢?早就意识到这个问题 ...
- Global::time2StrHHMM_DNT
/*************************************************** Created Date: 13 Jul 2013 Created By: Jimmy Xie ...
- FineUI 框架,RIA 富客户端应用的选择
FineUI 框架演示地址:http://www.fineui.com/demo/ 是asp.net 和extjs 结合的框架,可以快速创建企业应用程序的界面,节省开发时间,具体使用详见fineUI ...
- Spark菜鸟学习营Day2 分布式系统需求分析
Spark菜鸟学习营Day2 分布式系统需求分析 本分析主要针对从原有代码向Spark的迁移.要注意的是Spark和传统开发有着截然不同的思考思路,所以我们需要首先对原有代码进行需求分析,形成改造思路 ...