总结C#动态调用WCF接口的两种方法
程序员文章站
2022-07-02 22:06:50
如何使用
1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。
2、使用invoke的方式,但是需...
如何使用
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); //第二种方式<br><br>int result1 = wcfinvoke.invoke(t => t.add(1, 3));<br><br> <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(); } } } }
总结
第一种方式比较常见,第二种方式是我参考另外一个项目中的写法,其中的有一些细节我还没有搞明白,实现了这个功能后还需要再看看这部分代码,再消化消化。以上就是这篇文章的全部内容,希望能给大家带来一定的帮助,如果有疑问大家可以留言交流。