C # You can choose either of the two methods to dynamically call the WCF interface .,

Source: Internet
Author: User

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.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.