写一个类,用于动态生成WCFClient对象,无须每个WCF服务生成一个对应的配置,
public class WcfServiceFactory
{
/// <summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="action"></param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
public static void Execute<T>(string host = null, short port = 0,params Action<T>[] action) where T : class,IDisposable, ICommunicationObject, new()
{
Execute("COMM",host,port,action);
}
/// <summary>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bindingName">设置中Binding的名子.</param>
/// <param name="action">The action.</param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
/// <remarks></remarks>
public static void Execute<T>(string bindingName,string host = null, short port = 0,params Action<T>[] action) where T : class,IDisposable, ICommunicationObject, new()
{
Execute(null, bindingName,host,port, action);
}
/// <summary>
/// 执行WCF
/// </summary>
/// <typeparam name="T">服务Client类型</typeparam>
/// <param name="strServiceUrl">服务URL(如果为空,则从web.Config中读取名子为COMM的URL)</param>
/// <param name="bindingName">设置中Binding的名子</param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
/// <param name="exception">寻常</param>
/// <param name="action">要执行服务的方法列表</param>
/// <remarks></remarks>
public static void Execute<T>(string strServiceUrl, string bindingName, string host = null, short port = 0, Action<Exception> exception = null, params Action<T>[] action) where T : IDisposable, ICommunicationObject, new()
{
using (var t = GetInstance<T>(strServiceUrl,host,port, bindingName))
{
action.ToList().ForEach(f =>
{
if (exception != null)
{
try
{
f(t);
}
catch(Exception e)
{
exception(e);
}
}
else
{
f(t);
}
});
}
}
/// <summary>
/// 执行WCF,并返回值
/// </summary>
/// <typeparam name="TClient">服务Client类型</typeparam>
/// <typeparam name="TResult">返回值</typeparam>
/// <param name="strServiceUrl">服务URL(如果为空,则从web.Config中读取名子为COMM的URL)</param>
/// <param name="bindingName">设置中Binding的名子</param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
/// <param name="exception">寻常</param>
/// <param name="action">要执行服务的方法列表</param>
/// <returns></returns>
public static TResult ExecuteReturn<TClient, TResult>(string strServiceUrl, string bindingName, string host = null, short port = 0, Action<Exception> exception = null, params Func<TClient, TResult>[] action)
where TClient : IDisposable, ICommunicationObject, new()
{
TResult re = default(TResult);
using (var t = GetInstance<TClient>(strServiceUrl, host, port, bindingName))
{
action.ToList().ForEach(f =>
{
if (exception != null)
{
try
{
re = f(t);
}
catch (Exception e)
{
exception(e);
}
}
else
{
re = f(t);
}
});
}
return re;
}
/// <summary>
/// 执行WCF
/// </summary>
/// <typeparam name="T">服务Client类型</typeparam>
/// <param name="strServiceUrl">服务URL(如果为空,则从web.Config中读取名子为COMM的URL)</param>
/// <param name="bindingName">设置中Binding的名子</param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
/// <param name="action">要执行服务的方法列表</param>
/// <remarks></remarks>
public static void Execute<T>(string strServiceUrl, string bindingName, string host = null, short port = 0, params Action<T>[] action) where T : IDisposable, ICommunicationObject, new()
{
Execute(null, bindingName, host, port,null, action);
}
public static T GetInstance<T>(string strServiceUrl) where T : IDisposable, ICommunicationObject, new()
{
return GetInstance<T>(strServiceUrl,null);
}
/// <summary>
/// 返回设置中名子为bindingName的Uri
/// </summary>
/// <param name="bindingName"></param>
/// <returns></returns>
public static Uri GetEndpointAddress(string bindingName)
{
var client = WCFConfigHelper.GetChannelEndpointElement(bindingName,false);
if(client!=null)
{
return client.Address;
}
return null;
}
/// <summary>
/// 创建一个WCF服务实例
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="strServiceUrl">WCF Service Url</param>
/// <param name="host">(127.0.0.1)</param>
/// <param name="port">1-65535</param>
/// <param name="bindingName">设置中Binding的名子</param>
/// <returns>WCF服务实例</returns>
/// <remarks></remarks>
public static T GetInstance<T>(string strServiceUrl = null,string host = null,short port = 0,string bindingName = "COMM") where T : IDisposable, ICommunicationObject, new()
{
T _instance = default(T);
string serviceUri = strServiceUrl;
object[] paras = new object[2];
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
//返回设置
var bindConfig = WCFConfigHelper.GetBasicHttpBindingElement(bindingName, true);
bindConfig.ApplyConfiguration(binding);//应用设置
EndpointAddress address;
if (serviceUri == null)//从设置中返回URL
{
var client = WCFConfigHelper.GetChannelEndpointElement(bindingName, true);
var endpoint = client.Address;
string url = string.Format(endpoint.ToString(), GetServerName<T>());
Uri temp = new Uri(url);
Uri newUri = temp;
if (host != null)//如果输入参数中有HOST,则替换源设置中的HOST及端口
{
if (port == 0) port = 80;
newUri = new Uri(string.Format("http://{0}:{1}{2}", host, port, temp.PathAndQuery));
}
//WCF访问地址
address = new EndpointAddress(newUri);
}
else
{
address = new EndpointAddress(strServiceUrl);
}
//WCF设置及WCF地址
paras[0] = binding;
paras[1] = address;
ConstructorInfo constructor;
try
{
Type[] types = new Type[2];
types[0] = typeof(Binding);
types[1] = typeof(EndpointAddress);
constructor = typeof(T).GetConstructor(types);//声明调用哪个构造
}
catch (Exception)
{
return _instance;
}
if (constructor != null)
_instance = (T)constructor.Invoke(paras);//调用构造生成WCF访问类
return _instance;
}
/// <summary>
/// 根据CLIENT返回接口类型名子,
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
private static string GetServerName<T>()
{
Type t = typeof (T);
var interFace =
t.GetInterfaces().FirstOrDefault(w => w.IsDefined(typeof (ServiceContractAttribute), false));
if (interFace != null)
{
return interFace.Name;
}
return "";
}
}
读取设置类
/// <summary>
/// 读取WCF设置
/// </summary>
public static class WCFConfigHelper
{
#region Section
/// <summary>
/// 返回Bindings设置
/// </summary>
/// <returns></returns>
public static BindingsSection GetBindingsSection()
{
return ConfigurationManager.GetSection("system.serviceModel/bindings") as BindingsSection;
}
/// <summary>
/// 返回ServicesSection设置
/// </summary>
/// <returns></returns>
public static ServicesSection GetServicesSection()
{
return ConfigurationManager.GetSection("system.serviceModel/services") as ServicesSection;
}
/// <summary>
/// 返回BehaviorsSection设置
/// </summary>
/// <returns></returns>
public static BehaviorsSection GetBehaviorsSection()
{
return ConfigurationManager.GetSection("system.serviceModel/behaviors") as BehaviorsSection;
}
/// <summary>
/// 返回ClientSection设置
/// </summary>
/// <returns></returns>
public static ClientSection GetClientSection()
{
return ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;
}
#endregion
#region Binding
/// <summary>
/// 返回BasicHttpBinding设置
/// </summary>
/// <returns></returns>
public static BasicHttpBindingElement GetBasicHttpBindingElement(string name,bool returnDefault)
{
var list = GetBindingsSection().BasicHttpBinding.Bindings.Cast<BasicHttpBindingElement>();
var re = list.FirstOrDefault(w => w.Name == name);
if (re == null && returnDefault) re = list.FirstOrDefault();
return re;
}
/// <summary>
/// 返回NetTcpBindingElement设置
/// </summary>
/// <returns></returns>
public static NetTcpBindingElement GetNetTcpBindingElement(string name,bool returnDefault)
{
var list = GetBindingsSection().NetTcpBinding.Bindings.Cast<NetTcpBindingElement>();
var re = list.FirstOrDefault(w => w.Name == name);
if (re == null && returnDefault) re = list.FirstOrDefault();
return re;
}
/// <summary>
/// 返回WSHttpBindingElement设置
/// </summary>
/// <returns></returns>
public static WSHttpBindingElement GetWSHttpBindingElement(string name, bool returnDefault)
{
var list = GetBindingsSection().WSHttpBinding.Bindings.Cast<WSHttpBindingElement>();
var re = list.FirstOrDefault(w => w.Name == name);
if (re == null && returnDefault) re = list.FirstOrDefault();
return re;
}
#endregion
#region Behaviors
/// <summary>
/// 返回ServiceBehaviorElement设置
/// </summary>
/// <returns></returns>
public static ServiceBehaviorElement GetServiceBehaviorElement(string name, bool returnDefault)
{
var list = GetBehaviorsSection().ServiceBehaviors.Cast<ServiceBehaviorElement>();
var re = list.FirstOrDefault(w => w.Name == name);
if (re == null && returnDefault) re = list.FirstOrDefault();
return re;
}
#endregion
/// <summary>
/// 返回设置是的ChannelEndpointElement
/// </summary>
/// <param name="name"></param>
/// <param name="returnDefault"></param>
/// <returns></returns>
public static ChannelEndpointElement GetChannelEndpointElement(string name, bool returnDefault)
{
var list = GetClientSection().Endpoints.Cast<ChannelEndpointElement>();
var re = list.FirstOrDefault(w => w.Name == name);
if (re == null && returnDefault) re = list.FirstOrDefault();
return re;
}
}
使用方法
#region 通用Execute
/// <summary>
/// 使用设置接口设置执行WCF(默认接口设置为COMM)
/// </summary>
/// <typeparam name="TClient">WCF客户端代理</typeparam>
/// <param name="port">设置WCF服务的端口号</param>
/// <param name="action">要执行WCF的方法</param>
/// <param name="host">设置WCF服务的服务器名称或IP</param>
public static void Execute<TClient>(string host = null, short port = 0, Action<TClient> action = null)
where TClient : class, IDisposable, ICommunicationObject, new()
{
Execute(null, "COMM", host, port, action);
}
/// <summary>
/// 执行WCF
/// </summary>
/// <typeparam name="TClient">服务Client类型</typeparam>
/// <param name="strServiceUrl">服务URL(如果为空,则从web.Config中读取名子为COMM的URL)</param>
/// <param name="binding">设置中Binding的名子.</param>
/// <param name="port">设置WCF服务的端口号</param>
/// <param name="exceptionAction">调用WCF错误时执行的方法</param>
/// <param name="action">要执行服务的方法列表</param>
/// <param name="host">设置WCF服务的服务器名称或IP</param>
/// <remarks></remarks>
public static void Execute<TClient>(string strServiceUrl = null, string binding = null, string host = null,
short port = 0, Action<Exception> exceptionAction = null, Action<TClient> action = null)
where TClient : IDisposable, ICommunicationObject, new()
{
WcfServiceFactory.Execute(strServiceUrl, binding, host, port, exceptionAction, action);
}
/// <summary>
///
/// </summary>
/// <param name="strServiceUrl"></param>
/// <param name="binding"></param>
/// <param name="host"></param>
/// <param name="port"></param>
/// <param name="action"></param>
/// <typeparam name="TClient"></typeparam>
public static void Execute<TClient>(string strServiceUrl = null, string binding = null, string host = null,
short port = 0, Action<TClient> action = null)
where TClient : IDisposable, ICommunicationObject, new()
{
Execute(strServiceUrl, binding, host, port, null, action);
}
#endregion
#region 通用ExecuteReturn
/// <summary>
///
/// </summary>
/// <typeparam name="TClient">服务Client类型</typeparam>
/// <typeparam name="TResult">执行WCF服务的返回数据类型</typeparam>
/// <param name="strServiceUrl">设置WCF服务的地完整地址</param>
/// <param name="binding">设置中Binding的名子.</param>
/// <param name="host">设置WCF服务的服务器名称或IP</param>
/// <param name="port">设置WCF服务的端口</param>
/// <param name="exceptionAction"></param>
/// <param name="action">要执行WCF的方法</param>
/// <returns></returns>
public static TResult ExecuteReturn<TClient, TResult>(string strServiceUrl = null, string binding = null,
string host = null, short port = 0,
Action<Exception> exceptionAction = null,
Func<TClient, TResult> action = null)
where TClient : IDisposable, ICommunicationObject, new()
{
return WcfServiceFactory.ExecuteReturn(strServiceUrl, binding, host, port, exceptionAction, action);
}
#endregion
添加配置,aaa无用,但必须设置,COMM在调用时使用,{0}为服务名,自动匹配
<endpoint address="http://localhost:1234/Services/{0}.svc" binding="basicHttpBinding"
contract="aaa" name="COMM" />
<basicHttpBinding>
<binding name="AAA" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="96553600" maxBufferPoolSize="52428800" maxReceivedMessageSize="96553600"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="3200" maxStringContentLength="81920000"
maxArrayLength="91638400" maxBytesPerRead="409600" maxNameTableCharCount="91638400" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>