欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-15 09:34:37
如何使用 1、第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用。 2、使用invoke的方式,但是需...

如何使用

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

总结

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