0%

C#动态调用WCF接口,两种方式任你选。 - Danny Chen - 博客园

Excerpt

REFERENCE FROM : http://www.cnblogs.com/Leo_wl/p/4762784.html 写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作。 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项


REFERENCE FROM : http://www.cnblogs.com/Leo_wl/p/4762784.html

写在前面

           接触WCF还是它在最初诞生之处,一个分布式应用的巨作。 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF。 从这个小项目中我学会了两个地方: 1、利用IIS部署WCF服务,也就是大家接触到的发布SVC文件。2、动态调用WCF接口。

           在这个项目中接触WCF时遇到的其实不仅仅是这两个问题,甚至连IIS支持SVC文件也让我折腾了好几把,IIS都重新卸载了两次。 我在这篇文章里用两种方式来实现。

如何使用

      1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。

      2、使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可。

客户端调用DEMO

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

<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>

               binding="basicHttpBinding"

               bindingConfiguration="BasicHttpBinding_IDoubleService"

               contract="DoubleStone.WebHost.IDoubleService"

               name="BasicHttpBinding_IDoubleService" />

   </client>

 </system.serviceModel>

第一种调用方式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

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

   }

第二种调用方式

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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);

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

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<stringstring> 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<stringstring> 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<stringstring> 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<stringstring>(element.Name, element.Address.AbsoluteUri);

                }

            }

            throw configException;

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

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();

                }

            }

        }

    }

posted @ 2017-05-02 14:57  Danny Chen  阅读(1554)  评论()  编辑  收藏  举报