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 ...
随机推荐
- PDF转JPG
问题:对于上次解决PB调用不起PDF插件的问题,所以将PDF转换为HTML.但是转换完之后发现一个问题,pdf2htmlEX插件转换出的html只支持IE9以上,IE9以下的都会各式错乱, 所以只能换 ...
- Java面向对象课程小结
1.什么是对象?什么是类? 类和对象的关系 定义类的方法 方法五要素 new关键字 引用类型变量的赋值 null和nullException null大小写的区别 2.方法 重载和重写 构造 方法,带 ...
- ubuntu 安装与开始学习
下载地址 http://cn.ubuntu.com/download/ 经验: 1.遇到安装问题,首先尝试解读错误,再使用 ./configure --help 不行再上Stack overflo ...
- 移动端click时间延迟300
解决移动端click延迟事件方法,,引入fastclick.js 然后在script标签里面写上FastClick.attach(document.body); <!DOCTYPE html& ...
- snmp学习笔记
snmp5.5 client 包含头文件 #include <net-snmp/net-snmp-config.h> #include <net-snmp/net-snmp-incl ...
- python获取当前时间的用法
1.先导入库:import datetime 2.获取当前日期和时间:now_time = datetime.datetime.now() 3.格式化成我们想要的日期:strftime() 比如:“2 ...
- ASP.NET MVC Module
ASP.NET MVC Module 前言 在ASP.NET中管道模型是怎么来实现的?在请求处理流程一文中大概的讲述了Http Module和HttpApplication之间的关系,而并没有涉及到H ...
- ASP.NET MVC 从零开始 - 自动化部署(其二)
这篇文章是从我的 github 博客 http://lxconan.github.io 导入的. 这是这个系列的第五篇了,前四篇请参见: ASP.NET MVC 从零开始 – Create and R ...
- 可扩容分布式session方案
分布式session有以下几种方案: 1. 基于nfs(net filesystem)的session共享 将共享服务器目录mount各服务器的本地session目录,session读写受共享服务器i ...
- 大叔也学Xamarin系列
回到占占推荐博客索引 我就是我,请叫我仓储大叔 大叔听很多客户说,xamarin的资料网上太少了,是的,大叔也相信,因为大叔在学xamarin里确实很费劲,只能看看androd for java了,呵 ...