C#动态调用WCF接口

写在前面

接触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
//第一种方式
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>
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>
     
     <endpoint address="http://localhost:3000/DoubleService.svc"
               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();
                }
            }
        }
    }

总结

第一种方式比较常见,第二种方式是我参考另外一个项目中的写法,其中的有一些细节我还没有搞明白,实现了这个功能后还需要再看看这部分代码,再消化消化。由于是直接在项目中,所以没有提供源代码下载,有朋友需要的话我会整理出demo,稍后放出下载链接。

C#动态调用WCF接口的更多相关文章

  1. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  2. 动态调用wcf接口服务

    1.url:http://localhost:8002/名称.svc/basic(.svc结尾) 2.需要引用的命名空间System.ServiceModel 3.调用代码: public class ...

  3. C#动态调用WCF接口(3)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.S ...

  4. C#动态调用WCF接口(2)

    如何使用 1.第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用. 2.使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在I ...

  5. 动态调用WCF服务

    动态调用WCF服务,只需要提供*.svc地址, 1:命名空间: using System.ServiceModel.Channels;using System.ServiceModel; 2:创建访问 ...

  6. 动态调用WCF

    最近在做的一个项目中需要动态调用WCF地址,因为有很多终端服务器,而每台终端服务器上都部署一个WCF服务,中央服务器需要不定时调用其中某个或者多个WCF服务执行相关操作,因此添加引用及配置文件配置的方 ...

  7. 创建一个简单的WCF程序2——手动开启/关闭WCF服务与动态调用WCF地址

    一.创建WCF服务器 1.创建WCF服务器的窗体应用程序 打开VS2010,选择文件→新建→项目菜单项,在打开的新建项目对话框中,依次选择Visual C#→Windows→Windows窗体应用程序 ...

  8. c# 动态调用WCF方法笔记!

    //动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...

  9. 动态调用WebService接口的几种方式

    一.什么是WebService? 这里就不再赘述了,想要了解的====>传送门 二.为什么要动态调用WebService接口? 一般在C#开发中调用webService服务中的接口都是通过引用过 ...

随机推荐

  1. 什么是 CGI,什么是 IIS,什么是VPS

    该公司来到天.我们所从事的事情在网站上.这对我来说确实是一个很大的挑战.个人一直从事Android,对于web而一个开发网站server知识的几乎为零.在这里应该说,现在我只是有一个技术人员,昨天相遇 ...

  2. 傻瓜式破解linux--rootpassword

    破password的方法: 方法1.单用户模式改动 (表示进入到单用户模式) .按回车键.按b键启动.进入单用户模式,进行password改动.重新启动 init 5 口诀:e2e 空格1 回车b 开 ...

  3. 高级项目 它 集群环境建设(两)MySQL簇

    最后博文我们介绍一下相关概念集群,今天我们要介绍的博文MySQL相关内容集群. 1.MySQL集群简单介绍 MySQL群集技术在分布式系统中为MySQL数据提供了冗余特性,增强了安全性,使得单个MyS ...

  4. NLB+Application Request Route 网路负载均衡

    NLB网路负载均衡管理器详解   序言 在上一篇配置iis负载均衡中我们使用啦微软的ARR,我在那篇文章也中提到了网站的高可用性,但是ARR只能做请求入口的消息分发服务,这样如果我们的消息分发服务器给 ...

  5. gradle下载(转)

    http://services.gradle.org/distributions services.gradle.org/ distributions/ gradle-2.2.1-rc-1-all.z ...

  6. 《Java程序书面采访猿收藏》之 instanceof的作用是什么

    instanceof它是Java二元运算语言,它的作用是推断对象变量引用被指向的类型是一类(或接口.抽象类.父亲)示例.即,对象是否是它的一个实例离开它的类的权.返回boolean数据类型. 常见的使 ...

  7. ZOJ 3734 LIKE vs CANDLE

    题目意思:(13年长沙站的一道水DP,本人也去了,当时太水笔) 说俩个人竞争选票,每个人可以随机选择支持谁.每个人带有权重不同. 现在已经结束了投票阶段,你一个骇客 支持LIKE  你写了一个软件可以 ...

  8. JAVA基础编程50题(10-12题)具体解释

    一.描写叙述 1.一球从m米高度自由落下.每次落地后反跳回原高度的一半:再落下,求它在 第n次落地时.共经过多少米?第10次反弹多高? 2.有1.2.3.4个数字.能组成多少个互不同样且无反复数字的三 ...

  9. 返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性

    原文:返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性 [索引页][源码下载] 返璞归真 asp.net mvc (12) - asp.net mvc ...

  10. OpenJDK 阅读源代码 Java 实现字节流输入类

    Java 的输入输出总是给人一种非常混乱的感觉.要想把这个问题搞清楚.必须对各种与输入输出相关的类之间的关系有所了解. 仅仅有你了解了他们之间的关系.知道设计这个类的目的是什么.才干更从容的使用他们. ...