总结C#动态调用WCF接口的两种方法
如何使用
1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。
2、使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可。
客户端调用DEMO
//第一种方式 stringurl="http://localhost:3000/DoubleService.svc"; IDoubleServiceproxy=WcfInvokeFactory.CreateServiceByUrl<IDoubleService>(url); intresult=proxy.Add(1,3); //第二种方式<br><br>intresult1=WCFInvoke.Invoke(t=>t.Add(1,3));<br><br> <system.serviceModel> <behaviors> <endpointBehaviors> <behaviorname="NewBehavior"> <dataContractSerializermaxItemsInObjectGraph="65536000"/> </behavior> </endpointBehaviors> </behaviors> <bindings> <basicHttpBinding> <bindingname="BasicHttpBinding_IDoubleService" closeTimeout="01:00:00" openTimeout="01:00:00" sendTimeout="01:00:00" receiveTimeout="01:00:00" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"> <readerQuotasmaxDepth="128"maxStringContentLength="2147483647"maxArrayLength="16384"maxBytesPerRead="4096"maxNameTableCharCount="16384"/> </binding> </basicHttpBinding> <netMsmqBinding> <bindingname="NetMsmqBinding_IAsyncSender"> <securitymode="None"/> </binding> </netMsmqBinding> </bindings> <client> <endpointaddress="http://localhost:3000/DoubleService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDoubleService" contract="DoubleStone.WebHost.IDoubleService" name="BasicHttpBinding_IDoubleService"/> </client> </system.serviceModel>
第一种调用方式
publicclassWcfInvokeFactory
{
#regionWCF服务工厂
publicstaticTCreateServiceByUrl<T>(stringurl)
{
returnCreateServiceByUrl<T>(url,"basicHttpBinding");
}
publicstaticTCreateServiceByUrl<T>(stringurl,stringbing)
{
try
{
if(string.IsNullOrEmpty(url))thrownewNotSupportedException("ThisurlisnotNullorEmpty!");
EndpointAddressaddress=newEndpointAddress(url);
Bindingbinding=CreateBinding(bing);
ChannelFactory<T>factory=newChannelFactory<T>(binding,address);
returnfactory.CreateChannel();
}
catch(Exceptionex)
{
thrownewException("创建服务工厂出现异常.");
}
}
#endregion
#region创建传输协议
///<summary>
///创建传输协议
///</summary>
///<paramname="binding">传输协议名称</param>
///<returns></returns>
privatestaticBindingCreateBinding(stringbinding)
{
Bindingbindinginstance=null;
if(binding.ToLower()=="basichttpbinding")
{
BasicHttpBindingws=newBasicHttpBinding();
ws.MaxBufferSize=2147483647;
ws.MaxBufferPoolSize=2147483647;
ws.MaxReceivedMessageSize=2147483647;
ws.ReaderQuotas.MaxStringContentLength=2147483647;
ws.CloseTimeout=newTimeSpan(0,30,0);
ws.OpenTimeout=newTimeSpan(0,30,0);
ws.ReceiveTimeout=newTimeSpan(0,30,0);
ws.SendTimeout=newTimeSpan(0,30,0);
bindinginstance=ws;
}
elseif(binding.ToLower()=="nettcpbinding")
{
NetTcpBindingws=newNetTcpBinding();
ws.MaxReceivedMessageSize=65535000;
ws.Security.Mode=SecurityMode.None;
bindinginstance=ws;
}
elseif(binding.ToLower()=="wshttpbinding")
{
WSHttpBindingws=newWSHttpBinding(SecurityMode.None);
ws.MaxReceivedMessageSize=65535000;
ws.Security.Message.ClientCredentialType=System.ServiceModel.MessageCredentialType.Windows;
ws.Security.Transport.ClientCredentialType=System.ServiceModel.HttpClientCredentialType.Windows;
bindinginstance=ws;
}
returnbindinginstance;
}
#endregion
}
第二种调用方式
publicclassWCFInvoke
{
///<summary>
///你需要调用的服务契约
///</summary>
///<typeparamname="T"></typeparam>
///<paramname="func"></param>
///<returns></returns>
publicstaticTInvoke<T>(Func<IDoubleService,T>func)
{
IServiceInvokerserviceInvoker=newWCFServiceInvoker();
returnserviceInvoker.InvokeService(func);
}
}
publicinterfaceIServiceInvoker
{
voidInvokeService<T>(Action<T>invokeHandler)whereT:class;
TResltInvokeService<T,TReslt>(Func<T,TReslt>invokeHandler)whereT:class;
}
publicclassWCFServiceInvoker:IServiceInvoker
{
privatestaticreadonlyChannelFactoryManagerFactoryManager=newChannelFactoryManager();
privatestaticreadonlyClientSectionClientSection=
ConfigurationManager.GetSection("system.serviceModel/client")asClientSection;
publicvoidInvokeService<T>(Action<T>invokeHandler)whereT:class
{
KeyValuePair<string,string>endpointNameAddressPair=GetEndpointNameAddressPair(typeof(T));
vararg=FactoryManager.CreateChannel<T>(endpointNameAddressPair.Key,endpointNameAddressPair.Value);
varobj2=(ICommunicationObject)arg;
try
{
invokeHandler(arg);
}
finally
{
try
{
if(obj2.State!=CommunicationState.Faulted)
{
obj2.Close();
}
}
catch
{
obj2.Abort();
}
}
}
publicTResltInvokeService<T,TReslt>(Func<T,TReslt>invokeHandler)whereT:class
{
KeyValuePair<string,string>endpointNameAddressPair=GetEndpointNameAddressPair(typeof(T));
vararg=FactoryManager.CreateChannel<T>(endpointNameAddressPair.Key,endpointNameAddressPair.Value);
varobj2=(ICommunicationObject)arg;
try
{
returninvokeHandler(arg);
}
finally
{
try
{
if(obj2.State!=CommunicationState.Closed||obj2.State!=CommunicationState.Faulted)
{
obj2.Close();
}
}
catch
{
obj2.Abort();
}
}
}
privateKeyValuePair<string,string>GetEndpointNameAddressPair(TypeserviceContractType)
{
varconfigException=
newConfigurationErrorsException(
string.Format(
"Noclientendpointfoundfortype{0}.Pleaseaddthesection<client><endpointname=\"myservice\"address=\"http://address/\"binding=\"basicHttpBinding\"contract=\"{0}\"/></client>intheconfigfile.",
serviceContractType));
if(((ClientSection==null)||(ClientSection.Endpoints==null))||(ClientSection.Endpoints.Count<1))
{
throwconfigException;
}
foreach(ChannelEndpointElementelementinClientSection.Endpoints)
{
if(element.Contract==serviceContractType.ToString())
{
returnnewKeyValuePair<string,string>(element.Name,element.Address.AbsoluteUri);
}
}
throwconfigException;
}
}
publicclassChannelFactoryManager:IDisposable
{
privatestaticreadonlyDictionary<Type,ChannelFactory>Factories=newDictionary<Type,ChannelFactory>();
privatestaticreadonlyobjectSyncRoot=newobject();
publicvoidDispose()
{
Dispose(true);
}
publicvirtualTCreateChannel<T>()whereT:class
{
returnCreateChannel<T>("*",null);
}
publicvirtualTCreateChannel<T>(stringendpointConfigurationName)whereT:class
{
returnCreateChannel<T>(endpointConfigurationName,null);
}
publicvirtualTCreateChannel<T>(stringendpointConfigurationName,stringendpointAddress)whereT:class
{
Tlocal=GetFactory<T>(endpointConfigurationName,endpointAddress).CreateChannel();
((IClientChannel)local).Faulted+=ChannelFaulted;
returnlocal;
}
protectedvirtualChannelFactory<T>GetFactory<T>(stringendpointConfigurationName,stringendpointAddress)
whereT:class
{
lock(SyncRoot)
{
ChannelFactoryfactory;
if(!Factories.TryGetValue(typeof(T),outfactory))
{
factory=CreateFactoryInstance<T>(endpointConfigurationName,endpointAddress);
Factories.Add(typeof(T),factory);
}
return(factoryasChannelFactory<T>);
}
}
privateChannelFactoryCreateFactoryInstance<T>(stringendpointConfigurationName,stringendpointAddress)
{
ChannelFactoryfactory=null;
factory=!string.IsNullOrEmpty(endpointAddress)?newChannelFactory<T>(endpointConfigurationName,newEndpointAddress(endpointAddress)):newChannelFactory<T>(endpointConfigurationName);
factory.Faulted+=FactoryFaulted;
factory.Open();
returnfactory;
}
privatevoidChannelFaulted(objectsender,EventArgse)
{
varchannel=(IClientChannel)sender;
try
{
channel.Close();
}
catch
{
channel.Abort();
}
}
privatevoidFactoryFaulted(objectsender,EventArgsargs)
{
varfactory=(ChannelFactory)sender;
try
{
factory.Close();
}
catch
{
factory.Abort();
}
Type[]genericArguments=factory.GetType().GetGenericArguments();
if((genericArguments.Length==1))
{
Typekey=genericArguments[0];
if(Factories.ContainsKey(key))
{
Factories.Remove(key);
}
}
}
protectedvirtualvoidDispose(booldisposing)
{
if(disposing)
{
lock(SyncRoot)
{
foreach(TypetypeinFactories.Keys)
{
ChannelFactoryfactory=Factories[type];
try
{
factory.Close();
}
catch
{
factory.Abort();
}
}
Factories.Clear();
}
}
}
}
总结
第一种方式比较常见,第二种方式是我参考另外一个项目中的写法,其中的有一些细节我还没有搞明白,实现了这个功能后还需要再看看这部分代码,再消化消化。以上就是这篇文章的全部内容,希望能给大家带来一定的帮助,如果有疑问大家可以留言交流。