C#动态调用WCF接口
C#动态调用WCF接口
写在前面
接触WCF还是它在最初诞生之处,一个分布式应用的巨作。 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF。 从这个小项目中我学会了两个地方: 1、利用IIS部署WCF服务,也就是大家接触到的发布SVC文件。2、动态调用WCF接口。
在这个项目中接触WCF时遇到的其实不仅仅是这两个问题,甚至连IIS支持SVC文件也让我折腾了好几把,IIS都重新卸载了两次。 我在这篇文章里用两种方式来实现。
如何使用
1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。
2、使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可。
客户端调用DEMO
1
2
3
4
5
6
7
|
//第一种方式 IDoubleService proxy = WcfInvokeFactory.CreateServiceByUrl<IDoubleService>(url); int result = proxy.Add(1, 3); //第二种方式<br><br>int result1 = WCFInvoke.Invoke(t => t.Add(1, 3));<br><br> |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name= "NewBehavior" > <dataContractSerializer maxItemsInObjectGraph= "65536000" /> </behavior> </endpointBehaviors> </behaviors> <bindings> <basicHttpBinding> <binding name= "BasicHttpBinding_IDoubleService" closeTimeout= "01:00:00" openTimeout= "01:00:00" sendTimeout= "01:00:00" receiveTimeout= "01:00:00" maxBufferSize= "2147483647" maxBufferPoolSize= "524288" maxReceivedMessageSize= "2147483647" > <readerQuotas maxDepth= "128" maxStringContentLength= "2147483647" maxArrayLength= "16384" maxBytesPerRead= "4096" maxNameTableCharCount= "16384" /> </binding> </basicHttpBinding> <netMsmqBinding> <binding name= "NetMsmqBinding_IAsyncSender" > <security mode= "None" /> </binding> </netMsmqBinding> </bindings> <client> binding= "basicHttpBinding" bindingConfiguration= "BasicHttpBinding_IDoubleService" contract= "DoubleStone.WebHost.IDoubleService" name= "BasicHttpBinding_IDoubleService" /> </client> </system.serviceModel> |
第一种调用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
public class WcfInvokeFactory { #region WCF服务工厂 public static T CreateServiceByUrl<T>( string url) { return CreateServiceByUrl<T>(url, "basicHttpBinding" ); } public static T CreateServiceByUrl<T>( string url, string bing) { try { if ( string .IsNullOrEmpty(url)) throw new NotSupportedException( "This url is not Null or Empty!" ); EndpointAddress address = new EndpointAddress(url); Binding binding = CreateBinding(bing); ChannelFactory<T> factory = new ChannelFactory<T>(binding, address); return factory.CreateChannel(); } catch (Exception ex) { throw new Exception( "创建服务工厂出现异常." ); } } #endregion #region 创建传输协议 /// <summary> /// 创建传输协议 /// </summary> /// <param name="binding">传输协议名称</param> /// <returns></returns> private static Binding CreateBinding( string binding) { Binding bindinginstance = null ; if (binding.ToLower() == "basichttpbinding" ) { BasicHttpBinding ws = new BasicHttpBinding(); ws.MaxBufferSize = 2147483647; ws.MaxBufferPoolSize = 2147483647; ws.MaxReceivedMessageSize = 2147483647; ws.ReaderQuotas.MaxStringContentLength = 2147483647; ws.CloseTimeout = new TimeSpan(0, 30, 0); ws.OpenTimeout = new TimeSpan(0, 30, 0); ws.ReceiveTimeout = new TimeSpan(0, 30, 0); ws.SendTimeout = new TimeSpan(0, 30, 0); bindinginstance = ws; } else if (binding.ToLower() == "nettcpbinding" ) { NetTcpBinding ws = new NetTcpBinding(); ws.MaxReceivedMessageSize = 65535000; ws.Security.Mode = SecurityMode.None; bindinginstance = ws; } else if (binding.ToLower() == "wshttpbinding" ) { WSHttpBinding ws = new WSHttpBinding(SecurityMode.None); ws.MaxReceivedMessageSize = 65535000; ws.Security.Message.ClientCredentialType = System.ServiceModel.MessageCredentialType.Windows; ws.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows; bindinginstance = ws; } return bindinginstance; } #endregion } |
第二种调用方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class WCFInvoke { /// <summary> /// 你需要调用的服务契约 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="func"></param> /// <returns></returns> public static T Invoke<T>(Func<IDoubleService, T> func) { IServiceInvoker serviceInvoker= new WCFServiceInvoker(); return serviceInvoker.InvokeService(func); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
public interface IServiceInvoker { void InvokeService<T>(Action<T> invokeHandler) where T : class ; TReslt InvokeService<T, TReslt>(Func<T, TReslt> invokeHandler) where T : class ; } public class WCFServiceInvoker:IServiceInvoker { private static readonly ChannelFactoryManager FactoryManager = new ChannelFactoryManager(); private static readonly ClientSection ClientSection = ConfigurationManager.GetSection( "system.serviceModel/client" ) as ClientSection; public void InvokeService<T>(Action<T> invokeHandler) where T : class { KeyValuePair< string , string > endpointNameAddressPair = GetEndpointNameAddressPair( typeof (T)); var arg = FactoryManager.CreateChannel<T>(endpointNameAddressPair.Key, endpointNameAddressPair.Value); var obj2 = (ICommunicationObject)arg; try { invokeHandler(arg); } finally { try { if (obj2.State != CommunicationState.Faulted) { obj2.Close(); } } catch { obj2.Abort(); } } } public TReslt InvokeService<T, TReslt>(Func<T, TReslt> invokeHandler) where T : class { KeyValuePair< string , string > endpointNameAddressPair = GetEndpointNameAddressPair( typeof (T)); var arg = FactoryManager.CreateChannel<T>(endpointNameAddressPair.Key, endpointNameAddressPair.Value); var obj2 = (ICommunicationObject)arg; try { return invokeHandler(arg); } finally { try { if (obj2.State != CommunicationState.Closed || obj2.State != CommunicationState.Faulted) { obj2.Close(); } } catch { obj2.Abort(); } } } private KeyValuePair< string , string > GetEndpointNameAddressPair(Type serviceContractType) { var configException = new ConfigurationErrorsException( string .Format( "No client endpoint found for type {0}. Please add the section <client><endpoint name=\"myservice\" address=\"http://address/\" binding=\"basicHttpBinding\" contract=\"{0}\"/></client> in the config file." , serviceContractType)); if (((ClientSection == null ) || (ClientSection.Endpoints == null )) || (ClientSection.Endpoints.Count < 1)) { throw configException; } foreach (ChannelEndpointElement element in ClientSection.Endpoints) { if (element.Contract == serviceContractType.ToString()) { return new KeyValuePair< string , string >(element.Name, element.Address.AbsoluteUri); } } throw configException; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
public class ChannelFactoryManager : IDisposable { private static readonly Dictionary<Type, ChannelFactory> Factories = new Dictionary<Type, ChannelFactory>(); private static readonly object SyncRoot = new object (); public void Dispose() { Dispose( true ); } public virtual T CreateChannel<T>() where T : class { return CreateChannel<T>( "*" , null ); } public virtual T CreateChannel<T>( string endpointConfigurationName) where T : class { return CreateChannel<T>(endpointConfigurationName, null ); } public virtual T CreateChannel<T>( string endpointConfigurationName, string endpointAddress) where T : class { T local = GetFactory<T>(endpointConfigurationName, endpointAddress).CreateChannel(); ((IClientChannel)local).Faulted += ChannelFaulted; return local; } protected virtual ChannelFactory<T> GetFactory<T>( string endpointConfigurationName, string endpointAddress) where T : class { lock (SyncRoot) { ChannelFactory factory; if (!Factories.TryGetValue( typeof (T), out factory)) { factory = CreateFactoryInstance<T>(endpointConfigurationName, endpointAddress); Factories.Add( typeof (T), factory); } return (factory as ChannelFactory<T>); } } private ChannelFactory CreateFactoryInstance<T>( string endpointConfigurationName, string endpointAddress) { ChannelFactory factory = null ; factory = ! string .IsNullOrEmpty(endpointAddress) ? new ChannelFactory<T>(endpointConfigurationName, new EndpointAddress(endpointAddress)) : new ChannelFactory<T>(endpointConfigurationName); factory.Faulted += FactoryFaulted; factory.Open(); return factory; } private void ChannelFaulted( object sender, EventArgs e) { var channel = (IClientChannel)sender; try { channel.Close(); } catch { channel.Abort(); } } private void FactoryFaulted( object sender, EventArgs args) { var factory = (ChannelFactory)sender; try { factory.Close(); } catch { factory.Abort(); } Type[] genericArguments = factory.GetType().GetGenericArguments(); if ((genericArguments.Length == 1)) { Type key = genericArguments[0]; if (Factories.ContainsKey(key)) { Factories.Remove(key); } } } protected virtual void Dispose( bool disposing) { if (disposing) { lock (SyncRoot) { foreach (Type type in Factories.Keys) { ChannelFactory factory = Factories[type]; try { factory.Close(); } catch { factory.Abort(); } } Factories.Clear(); } } } } |
总结
第一种方式比较常见,第二种方式是我参考另外一个项目中的写法,其中的有一些细节我还没有搞明白,实现了这个功能后还需要再看看这部分代码,再消化消化。由于是直接在项目中,所以没有提供源代码下载,有朋友需要的话我会整理出demo,稍后放出下载链接。
C#动态调用WCF接口的更多相关文章
- C#动态调用WCF接口,两种方式任你选。
写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...
- 动态调用wcf接口服务
1.url:http://localhost:8002/名称.svc/basic(.svc结尾) 2.需要引用的命名空间System.ServiceModel 3.调用代码: public class ...
- C#动态调用WCF接口(3)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.S ...
- C#动态调用WCF接口(2)
如何使用 1.第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用. 2.使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在I ...
- 动态调用WCF服务
动态调用WCF服务,只需要提供*.svc地址, 1:命名空间: using System.ServiceModel.Channels;using System.ServiceModel; 2:创建访问 ...
- 动态调用WCF
最近在做的一个项目中需要动态调用WCF地址,因为有很多终端服务器,而每台终端服务器上都部署一个WCF服务,中央服务器需要不定时调用其中某个或者多个WCF服务执行相关操作,因此添加引用及配置文件配置的方 ...
- 创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址
一.创建WCF服务器 1.创建WCF服务器的窗体应用程序 打开VS2010,选择文件→新建→项目菜单项,在打开的新建项目对话框中,依次选择Visual C#→Windows→Windows窗体应用程序 ...
- c# 动态调用WCF方法笔记!
//动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...
- 动态调用WebService接口的几种方式
一.什么是WebService? 这里就不再赘述了,想要了解的====>传送门 二.为什么要动态调用WebService接口? 一般在C#开发中调用webService服务中的接口都是通过引用过 ...
随机推荐
- HDU 2504 又见GCD
又见GCD Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- android贴士Toast
转载请注明出处:http://blog.csdn.net/droyon/article/details/42009015 我们可以用androd提供toast控制,但在使用过程中,给我们发了很多Toa ...
- android studio学习
http://blog.csdn.net/ryantang03/article/details/8948037 http://www.it165.net/pro/html/201109/676.htm ...
- Java 并发专题 :闭锁 CountDownLatch 之一家人一起吃个饭
最近一直整并发这块东西,顺便写点Java并发的例子,给大家做个分享,也强化下自己记忆. 每天起早贪黑的上班,父母每天也要上班,话说今天定了个饭店,一家人一起吃个饭,通知大家下班去饭店集合.假设:3个人 ...
- java序列化是什么和反序列化和hadoop序列化
1.什么是序列化和系列化DE- 神马是序列化它,序列化是内存中的对象状态信息,兑换字节序列以便于存储(持久化)和网络传输.(网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什 ...
- vmware 10 注冊码
先安装VMware Workstation 10.0原版,然后用以下的随意一个VMware Workstation序列号注冊 1Y0LW-4WJ9N-LZ5G9-Z81QP-92PN7 JU052-F ...
- Directx11学习笔记【十八】 Blending混合
本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5634580.html 在d3d11中是按frame来渲染物体的,在 ...
- 使用 WPF 实现所见即所得HTML编辑器
Introduction In this tip, you will learn the use of WPF webbrowser control and the use of the librar ...
- jQuery 操作 input 之 checkbox
jQuery 操作 input 之 checkbox 一片 HTML 清单: <input type="checkbox" name="hobby" va ...
- 同一个PC只能运行一个应用实例(考虑多个用户会话情况)
原文:同一个PC只能运行一个应用实例(考虑多个用户会话情况) class Program { private static Mutex m; [STAThread] static void Main( ...