Wcf:可配置的服务调用方式

添加wcf服务引用时,vs.net本来就会帮我们在app.config/web.config里生成各种配置,这没啥好研究的,但本文谈到的配置并不是这个。先看下面的图:

通常,如果采用.NET的WCF技术来架构SOA风格的应用,我们会把项目做一些基本的分层,如上图:

01. contract层:通常定义服务的接口(即服务契约ServiceContract,指明该服务提供了哪些方法可供外部调用)、以及接口方法中传输的Model定义(即:数据契约DataContract,指明方法中的对象参数的Class定义)

02. implementation层:即服务接口的实现

03. host层:wcf最终需要一个宿主环境,如果是web应用,最简单的办法莫过于直接寄宿在IIS上

04. client层:即服务的消费方,如果是b/s应用,通常就是一个web application

实际部署时,一般将wcf服务层和client层分开部署,如下图:

如果并发数随着业务的增长而增长,不管是client层的website,还是服务层的service,加上其它技术,比如集群或负载均衡之类,可以很方便进行扩充。服务的实现逻辑也可以方便的单独的修改替换(前提是服务契约相对稳定)

但如果应用的规模较小,出于成本考虑,完全有可能Service层和Website Client部署在一台机器上,虽然1个IIS上架2个站点完全没有问题,但是总归有点不爽,既然都在一台机器上了,为啥还要自己调用自己,增加无谓的开销呢?

最好是在不修改原来代码的前提下,通过简单的配置文件修改,就能让原来远程调用WCF的方式,改成直接调用本地DLL程序集,反过来也一样,这样就比较灵活了。事实上,我们公司很多项目就是这样处理的,规模小的应用,直接全都部署在一台机器上,等应用规模上去了,再分开部署,代码完全不用动,只要修改相关配置即可。

原理其实非常简单,反射即可,先在Client层的web.config或app.config中,增加类似以下节点:

1   <appSettings>
2     <!--调用方式:Remote远程调用,Local本地调用(注:本地调用时,bin目录下必须有[服务实现类]的dll)-->
3     <add key="CallType" value="Remote"/>
4     <!--本地调用时,程序集的名称-->
5     <add key="AssemblyName" value="sjtu.wcf.demo.implementation"/>
6     <!--本地调用时,[服务实现类]的名称-->
7     <add key="ServiceTypeName" value="sjtu.wcf.demo.implementation.DemoService"/>
8   </appSettings>

CallType就决定了调用方式:“远程调用”或“本地DLL调用”。然后在本地写一个调用的Client类:(注:wcf的调用方式,参考了dudu的文章“享受无止境 - 改进版WCF Client”)

 1 using System;
 2 using System.Linq.Expressions;
 3 using System.Reflection;
 4 using System.ServiceModel;
 5 using sjtu.wcf.demo.client.configs;
 6
 7 namespace sjtu.wcf.demo.client
 8 {
 9     /// <summary>
10     /// Wcf客户端
11     /// </summary>
12     /// <typeparam name="T">ServiceContract接口</typeparam>
13     public class WcfClient<T> where T : class
14     {
15
16         private readonly string assemblyName;
17         private readonly string implTypeName;
18         private readonly string callType;
19
20         public WcfClient()
21         {
22             callType = ConfigHelper.CallType.ToLower();
23             if (callType == CallType.Local.ToString().ToLower())
24             {
25                 assemblyName = ConfigHelper.AssemblyName;
26                 implTypeName = ConfigHelper.ServiceTypeName;
27             }
28         }
29
30         /// <summary>
31         /// 对外提供的Call方法
32         /// </summary>
33         /// <typeparam name="R"></typeparam>
34         /// <param name="expression"></param>
35         /// <returns></returns>
36         public R Call<R>(Expression<Func<T, R>> expression)
37         {
38             if (callType == CallType.Local.ToString().ToLower())
39             {
40                 return InvokeLocalMethod<R>(expression);
41             }
42             return InvokeRemoteMethod<R>(expression);
43         }
44
45         /// <summary>
46         /// 调用本地程序集方法
47         /// </summary>
48         /// <typeparam name="R"></typeparam>
49         /// <param name="operation"></param>
50         /// <returns></returns>
51         private R InvokeLocalMethod<R>(Expression<Func<T, R>> operation)
52         {
53             Assembly asm = Assembly.Load(new AssemblyName(assemblyName));
54             T t = (T)asm.CreateInstance(implTypeName);
55             R result = operation.Compile().Invoke(t);
56             return result;
57         }
58
59         /// <summary>
60         /// 调用远程wcf方法
61         /// </summary>
62         /// <typeparam name="R"></typeparam>
63         /// <param name="operation"></param>
64         /// <returns></returns>
65         private R InvokeRemoteMethod<R>(Expression<Func<T, R>> operation)
66         {
67             ChannelFactory<T> channelFactory = new ChannelFactory<T>("*");
68
69             T channel = channelFactory.CreateChannel();
70             var client = (IClientChannel)channel;
71             client.Open();
72             R result = operation.Compile().Invoke(channel);
73             try
74             {
75                 if (client.State != CommunicationState.Faulted)
76                 {
77                     client.Close();
78                 }
79             }
80             catch
81             {
82                 client.Abort();
83             }
84             return result;
85         }
86     }
87 }

这样调用时,只需要一行代码即可:

1 var students = new WcfClient<IStudent>().Call(c => c.GetStudents("jerry"));

转载网址:http://www.cnblogs.com/yjmyzz/p/3372390.html

时间: 2024-10-12 20:17:04

Wcf:可配置的服务调用方式的相关文章

WCF系列之WCF服务调用方式

WCF服务调用通过两种常用的方式:一种是借助代码生成工具SvcUtil.exe或者添加服务引用的方式,一种是通过ChannelFactory直接创建服务代理对象进行服务调用. 通过SvcUtil.exe的方式调用服务 SvcUtil.exe是一个命令行工具,位于:C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin目录下,可以将SvcUtil.exe添加到VS2010中方便以后的运用,添加方式:在VS2010的Tools菜单中选择External T

不同服务调用方式的比较

1.同步服务调用 上图是同步调用的原理图,用户线程在完成消息序列化之后,把消息投递到通信框架,然后同步阻塞,等待通信线程发送 请求并接收到应答之后,唤醒用户同步阻塞的线程,用户线程获取到应答后返回. 2.异步服务调用 异步调用是基于JDK的Future机制,Future代表了异步操作的结果,用户可以通过调用它的get方法获取结果. 原理如图所示. 1.消费者调用服务端发布接口,接口调用由服务框架封装成动态代理,发起远程服务调用. 2.通信框架异步发送消息,如果没有发生I/O异常,返回. 3.消息

WCF学习笔记(基于REST规则方式)

一.WCF的定义 WCF是.NET 3.0后开始引入的新技术,意为基于windows平台的通讯服务. 首先在学习WCF之前,我们也知道他其实是加强版的一个面向服务(SOA)的框架技术. 如果熟悉WebService就会知道WebService是基于XML+XSD,SOAP和WSDL三大技术,当然他也是采用HTTP协议的通信,严格来说WebService是一种面向服务开发的标准.而ASP.NET WebService则是微软平台下的服务. WCF其实一定程度上就是ASP.NET Web Servi

Spring Cloud Ribbon---微服务调用和客户端负载均衡

前面分析了Eureka的使用,作为服务注册中心,Eureka 分为 Server 端和 Client 端,Client 端作为服务的提供者,将自己注册到 Server 端,Client端高可用的方式是使用多机部署然后注册到Server,Server端为了保证服务的高可用,也可以使用多机部署的方式.前面简单搭建了Eureka Client 和 Server,然后将Client成功注册到 Server,本节我们将来看看如何调用Eureka服务,在多机部署情况下如何保证负载均衡.Spring Clou

WCF 配置终结点并调用服务

wcf通过xml文件配置终结点什么的感觉有点小麻烦,个人还是觉得用代码形式配置比较好,当然在发布的时候可能会比较麻烦,需要重新编译... 下面将wcf service寄宿在控制台应用程序中并配置终结点: ? 1 2 3 4 5 6 7 8 9 10 11 using (var host = new ServiceHost(typeof(Service1),                                               new Uri("http://localhos

WCF如何通过契约加编码方式调用

WCF采用基于契约的服务调用方法,通过System.ServiceModel.ChannelFactory<TChannel>直接创建服务代理对象. 创建服务代理 public static T Create<T>(string endpointName) { if (string.IsNullOrEmpty(endpointName)) { #region 默认配置,根据类名,赋值endpointName #endregion throw new ArgumentNullExce

调用WCF不需要添加服务引用,使用一个WCFHelper类就可以

效果图: 调用过程: string WCFURL = "http://localhost:100/Service1.svc"; UserRequest user = new UserRequest { UserName = UserName.Text, Address = Address.Text, Email = Email.Text }; string request = "{\"request\":" + new JavaScriptSer

WCF多种调用方式兼容

原文:WCF多种调用方式兼容 1.能被ajax get 2.能post 3.wcf正常调用 实现: 1 [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 2 [JavascriptCallbackBehavior(UrlParameterName = "jsoncallback")] 3 public class WCFJsonTest :

异步服务之间的调用方式

本文为原作,转载请发自原文出处 http://www.cnblogs.com/jermmy/p/6752950.html,谢谢合作! 对与异步服务之间的调用方式LZ只使用了future和callback两种方式,其实异步服务之间的调用有以下几种 1.oneway oneway 是一种只管发送而不管结果的交互方式,不关心服务方的请求结果如何,属于一种单向的通知 2.future 多线程获取数据以及异步交互获取数据使用callable和future的组合是多服务中经常用到的,该接口在juc包中,ca