总结C#动态调用WCF接口的两种方法

如何使用

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

总结

第一种方式比较常见,第二种方式是我参考另外一个项目中的写法,其中的有一些细节我还没有搞明白,实现了这个功能后还需要再看看这部分代码,再消化消化。以上就是这篇文章的全部内容,希望能给大家带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • C# WCF简单入门图文教程(VS2010版)

    在这个例子中我们将使用VS2010创建一个WCF服务,其中会了解[DataContract][ServiceContract]等特性. 内置的WCFSVCHost,并使用"WCF测试客户端"来测试我们创建的服务. 注意下面的所有类.接口及方法都添加了public的访问级别. 一.建立一个WCF服务库 创建一个WCF服务库项目 在解决方案中会自动为我们生成两个类文件"IService1.cs"和"Service1.cs". 这两个类文件是两个WCF

  • C# yield在WCF中的错误用法(一)

    在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题.这里要说的是另一个问题:对于返回类型为IEnumerable<T>的方法来说,我们可以使用yield return的方式来输出返回集合的元素.但是如果我们不了解yield 关键字背后的实现机制,很有可能造成很大的问题. 这是一个WCF相关的问题,我想99%的人都有可能会犯这样的错误--即使你对yield了解得非常透彻.闲话少说,我们通过一个简单的实例来说明这个问

  • C# 一个WCF简单实例

    WCF实例(带步骤) 复制代码 代码如下: <xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 本篇转自百度文档,自己试过,确实可以用. 以订票为例简单应用wcf 新建一个wcf服务应用程序 在IService1.cs定义服务契约 复制代码 代码如下: namespace WcfDemo { // 注意: 如果更改此处的接口名称 "IService

  • C#创建WCF服务控制台应用程序详解

    一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(IIS) 1.进入"控制面板",打开"程序和功能",点击左上角的"启用或关闭Windows功能"后,在".NET Framework 4.6 高级服务"中的子节点选中"WCF 服务",如下图所示: 2.再找到&qu

  • C# yield在WCF中的错误使用(二)

    昨天写了<yield在WCF中的错误使用--99%的开发人员都有可能犯的错误[上篇]>,引起了一些讨论.关于yield关键字这个语法糖背后的原理(C#编译器将它翻译成什么)其实挺简单,虽然有时候因为误用它会导致一些问题,但是它本无过错.接下来,我们通过这篇短文简单地谈谈我所理解的yield. 目录 一.先看一个简单的例子 二.了解本质,只需要看看yield最终编译成什么 三.回到WCF的例子 一.先看一个简单的例子 我们现在看一个简单的例子.我们在一个Console应用中编写了如下一段简单的程

  • 关于.NET/C#/WCF/WPF 打造IP网络智能视频监控系统的介绍

    OptimalVision网络视频监控系统 OptimalVision(OV)网络视频监控系统(Video Surveillance System),是一套基于.NET.C#.WCF.WPF等技术构建的IP网络视频监控系统.设计与实现该系统的初衷是希望在家用电脑中部署该系统,连接本地或局域网设备,通过浏览器或手机客户端浏览宝宝实时视频,也就是俗称的"宝宝在线"或"家庭看护". 但由于业余时间总是有限,完成系统中的服务.配置.采集.传输和桌面GUI部分后,继续完成后续

  • 总结C#动态调用WCF接口的两种方法

    如何使用 1.第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用. 2.使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可. 客户端调用DEMO //第一种方式 string url = "http://localhost:3000/DoubleService.svc"; IDoubleService proxy = WcfInvokeFactory.CreateServic

  • Java动态验证码单线设计的两种方法

    1.java的动态验证码我这里将介绍两种方法: 一:根据java本身提供的一种验证码的写法,这种呢只限于大家了解就可以了,因为java自带的模式编写的在实际开发中是没有意义的,所以只供学习一下就可以了,待会讲解的第二种呢就是我们需要掌握的一种模式了: 第一种的代码如下: import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import

  • vs2019 实现C#调用c++的dll两种方法

    1.托管与非托管的区别 链接地址(仅供参考) 除了链接中的,在实用角度出发: 非托管需要一个个声明引用,就很繁琐 但是托管(虽然麻烦)不用声明,只需要调好配置即可,还是比较方便的 为什么写这个博客,也是因为不同版本vs2017和vs2019有所区别,托管就容易踩坑,希望大家能看看,解决问题(我也很菜,大佬轻喷) 2.非托管类的实现 第一步:创建C++空项目(命名Caculate)添加一个类AddOperate .h代码部分: #pragma once extern "C" _decls

  • Vue3引入axios封装接口的两种方法实例

    目录 第一种 1.安装 2.新建一个http.js文件 3.使用 第二种 1.安装 2.新建 3.http.js 4.request.js 总结 第一种 1.安装 npm install axios -S 2.新建一个http.js文件 import axios from "axios"; import qs from "qs"; import { Dialog, Toast } from "vant"; // axios.defaults.ba

  • 动态加载jQuery的两种方法实例分析

    本文实例讲述了动态加载jQuery的两种方法.分享给大家供大家参考.具体如下: 第一种方法参考本站之前有人发的代码,增加了加载检测: 第二种方法来自去年的12306刷票脚本. 第一种方法: function withjQuery(callback) { if(!(window.jQuery)) { var js = document.createElement('script'); js.setAttribute('src', 'https://dynamic.12306.cn/otsweb/j

  • javascript 动态生成css代码的两种方法

    javascript 动态生成css代码的两种方法 有时候我们需要利用js来动态生成页面上style标签中的css代码,方法很直接,就是直接创建一个style元素,然后设置style元素里面的css代码,最后把它插入到head元素中.但有些兼容性问题我们需要解决.首先在符合w3c标准的浏览器中我们只需要把要插入的css代码作为一个文本节点插入到style元素中即可,而在IE中则需要利用style元素的styleSheet.cssText来解决.还需要注意的就是在有些版本IE中一个页面上style

  • Vue 实现列表动态添加和删除的两种方法小结

    下面将介绍两种方式实现动态添加和删除列表 1.不使用组件 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue 测试实例 - vue实现列表增加和删除</title> <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script&g

  • java调用Restful接口的三种方法

    目录 1,基本介绍 2,HttpURLConnection实现 3.HttpClient实现 4.Spring的RestTemplate 1,基本介绍 Restful接口的调用,前端一般使用ajax调用,后端可以使用的方法比较多, 本次介绍三种: 1.HttpURLConnection实现 2.HttpClient实现 3.Spring的RestTemplate 2,HttpURLConnection实现 @Controller public class RestfulAction { @Aut

  • sql动态行转列的两种方法

    第一种方法: 复制代码 代码如下: select *from ( select Url,case  when  Month=01 then  '1月' when  Month=02 then '2月' when  Month=03 then  '3月' when  Month=04 then '4月' when  Month=05 then  '5月' when  Month=06 then '6月' when  Month=07 then  '7月' when  Month=08 then '

  • 解析Silverlight调用WCF/Rest异常的解决方法

    新建Rest服务接口: 复制代码 代码如下: [ServiceContract]public interface IService1{    [OperationContract]    string GetData(int value);} 接着新建一个服务实现类: 复制代码 代码如下: public class Service1 : IService1{    public string GetData(int value)    {        int i = 0;        int

随机推荐