C#动态调用WCF接口,两种方式任你选。
写在前面
接触WCF还是它在最初诞生之处,一个分布式应用的巨作。 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF。 从这个小项目中我学会了两个地方: 1、利用IIS部署WCF服务,也就是大家接触到的发布SVC文件。2、动态调用WCF接口。
在这个项目中接触WCF时遇到的其实不仅仅是这两个问题,甚至连IIS支持SVC文件也让我折腾了好几把,IIS都重新卸载了两次。 我在这篇文章里用两种方式来实现。
如何使用
1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。
2、使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可。
客户端调用DEMO
//第一种方式
string url = "http://localhost:3000/DoubleService.svc";
IDoubleService proxy = WcfInvokeFactory.CreateServiceByUrl<IDoubleService>(url);
int result = proxy.Add(1, 3); //第二种方式 int result1 = WCFInvoke.Invoke(t => t.Add(1, 3));
<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> <endpoint address="http://localhost:3000/DoubleService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IDoubleService"
contract="DoubleStone.WebHost.IDoubleService"
name="BasicHttpBinding_IDoubleService" /> </client>
</system.serviceModel>
第一种调用方式
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
}
第二种调用方式
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);
}
}
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;
}
}
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# 调用HTTP接口两种方式
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...
- C#动态调用WCF接口
C#动态调用WCF接口 写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项 ...
- java动态获取WebService的两种方式(复杂参数类型)
java动态获取WebService的两种方式(复杂参数类型) 第一种: @Override public OrderSearchListRes searchOrderList(Order_Fligh ...
- 调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)
调用init方法 两种方式 一个是浏览器方法 一个是 xml中手工配置(load-on-startup)
- Unity调用Android的两种方式:其一、调用jar包
unity在Android端开发的时候,免不了要调用Java:Unity可以通过两种方式来调用Android:一是调用jar.二是调用aar. 这篇文章主要讲解怎么从无到有的生成一个jar包,然后un ...
- Spring容器自动调用方法的两种方式
先看一个Spring中Bean的实例化过程: 1.配置文件中指定Bean的init-method参数 <bean class="com.jts.service.UserService& ...
- 动态调用wcf接口服务
1.url:http://localhost:8002/名称.svc/basic(.svc结尾) 2.需要引用的命名空间System.ServiceModel 3.调用代码: public class ...
- 软件调用QML的两种方式
一.两种方式 二.方式1[对窗口的控制权在QML] 三.方式2[对窗口的控制权在C++]
- C# .NET 动态调用webservice的三种方式
转载自 百度文库 http://wenku.baidu.com/link?url=Q2q50wohf5W6UX44zqotXFEe_XOMaib4UtI3BigaNwipOHKNETloMF4ax4W ...
随机推荐
- bzoj3555: [Ctsc2014]企鹅QQ (Hash)
枚举每个分段的点,每次O(n)更新左边和右边的hash值 然后用双指针O(n)计算答案 #include<stdio.h> #include<string.h> #includ ...
- Android分享一款漂亮的折叠书架菜单
一个Android折叠书架菜单,效果极佳,给人的视觉感觉很好,便于使用. FoldingMenu
- 【二】jekyll 的使用
本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...
- mongodb搭建和基本语法
下载安装包 https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.0.0-signed.msi?_ga=1.2206 ...
- linux 实践2.2 编译模块
1. 理解模块原理 linux模块是一些可以作为独立程序来编译的函数和数据类型的集合.之所以提供模块机制,是因为Linux本身是一个单内核.单内核由于所有内容都集成在一起,效率很高,但可扩展性和可维 ...
- PC使用网线上网的条件下,通过PC的Wifi共享提供手机上网教程
场景和目标 你有一个笔记本(或装有无线网卡的PC),可以通过网线上网,但是没有无线路由器.现在想要通过笔记本的无线网,让手机也能共享wifi上网. 环境 Win7 操作系统.带有无线网卡的PC或笔记本 ...
- TODO:软件升级的那些事
TODO:软件升级的那些事 软件升级,指软件从低版本向高版本的更新.由于高版本常常修复低版本的部分BUG,所以经历了软件升级,一般都会比原版本的性能更好,得到优化的效果,用户也能有更好的体验. 最近常 ...
- JavaScript利用replace更改所有符合条件字符
利用replace替换字符串时,在正常使用情况下默认只能更改匹配到的第一个字符 var a=new String("fffffddd"); console.log(a.replac ...
- mybatis的一些小总结
好长时间没用mybatis了,现在项目忽然用mybatis,用的过程中出现了些问题,虽然解决了,不过这花的时间有些长了.总结用的过程中出现的一些问题 1.mapper.xml 之前一直用的自动生成,现 ...
- JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...