C # You can choose either of the two methods to dynamically call the WCF interface .,
Preface
It was the first time that I came into contact with WCF, a masterpiece of distributed applications. From the beginning to the present, there have been very few projects in use, not to mention in-depth research on the internal implementation mechanism and principles of WCF. Recently, I used WCF for my own project. I learned two ways from this small project: 1. Using IIS to deploy the WCF Service, that is, publishing the SVC file. 2. dynamically call the WCF interface.
In this project, I encountered not only these two problems, but even the support for SVC files in IIS also caused me to toss several times, and IIS was uninstalled twice. In this article, I use two methods.
How to Use
1. The first method is simple and popular, because it can be solved without any configuration files. You only need to know the service contract interface and service address to call it.
2. Use the Invoke method, but you need to configure the WCF on the call client, and then encapsulate the service contract interface in the Invoke class.
Client call DEMO
// The first method is string url = "http: // localhost: 3000/DoubleService. svc "; IDoubleService proxy = WcfInvokeFactory. createServiceByUrl <IDoubleService> (url); int result = proxy. add (1, 3); // method 2
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>
Method 1
Public class WcfInvokeFactory {# region WCF Service Factory 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 ("an Exception occurred when creating a service factory. ");}} # endregion # region create a transfer protocol /// <summary> /// create a transfer protocol /// </summary> /// <param name = "binding"> transfer protocol name </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. maxcompute edmessagesize = 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. maxcompute edmessagesize = 65535000; ws. security. mode = SecurityMode. none; bindinginstance = ws;} else if (binding. toLower () = "wshttpbinding") {WSHttpBinding ws = new WSHttpBinding (SecurityMode. none); ws. maxcompute edmessagesize = 65535000; ws. security. message. clientCredentialType = System. serviceModel. messageCredentialType. windows; ws. security. transport. clientCredentialType = System. serviceModel. httpClientCredentialType. windows; bindinginstance = ws;} return bindinginstance;} # endregion}
Method 2
Public class WCFInvoke {// <summary> // the service contract you need to call /// </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(); } } } }
Summary
The first method is more common, and the second method is to refer to the writing method in another project. I have not understood some details yet, after implementing this function, you need to check the code and digest it. Because it is directly in the project, the source code download is not provided. If you need it, I will sort out the demo and release the download link later.