以编程方式创建WCF客户端

本文关键字:WCF 客户端 创建 方式 编程 | 更新日期: 2023-09-27 17:53:10

我有一个正在运行的WCF服务和一个我正在工作的客户端,但是目前我已经在我的客户端引用了该服务。

我想动态创建客户端引用。

这是我的配置文件:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=e77a5e561934e089" requirePermission="false" />
  </configSections>
  <system.serviceModel>
    <services>
      <!-- This section is optional with the new configuration model
           introduced in .NET Framework 4. -->
      <service name="Service.CalculatorService" behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://xx.xx.xx.xx:20001/Service/service" />
          </baseAddresses>
        </host>
        <!-- this endpoint is exposed at the base address provided by host: http://xx.xx.xx.xx:20001/Service/service  -->
        <endpoint address="" binding="wsHttpBinding" contract="Service.IReportData" bindingConfiguration="CustomBinding" />
        <!-- the mex endpoint is exposed at http://xx.xx.xx.xx:20001/Service/service/mex -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="CustomBinding" closeTimeout="00:02:00" openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:02:00" maxReceivedMessageSize="2147483647">
          <security mode="None">
            <transport clientCredentialType="None" />
            <message establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="True" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.data>
    <DbProviderFactories>
      <remove invariant="System.Data.SQLite.EF6" />
      <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
    </DbProviderFactories>
  </system.data>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
    </providers>
  </entityFramework>
</configuration>

我已经在谷歌上搜索了大约一个星期,发现了下面的代码片段,我一直试图使用我在stackoverflow上找到的。

链接到我发现它的帖子是:配置wcf服务编程

public virtual ChannelFactory<T> Proxy<T>(string address)
        {
            //Validate Address
            if (string.IsNullOrEmpty(address)) throw new ArgumentNullException("Address can not be null or empty.");
            //Address
            EndpointAddress endpointAddress = new EndpointAddress(address);
            //Binding
            WSHttpBinding wsHttpBinding = new WSHttpBinding(SecurityMode.None, false);
            wsHttpBinding.OpenTimeout = wsHttpBinding.CloseTimeout = new TimeSpan(0, 1, 0);
            wsHttpBinding.ReceiveTimeout = wsHttpBinding.SendTimeout = new TimeSpan(0, 10, 0);
            wsHttpBinding.MaxReceivedMessageSize = wsHttpBinding.MaxBufferPoolSize = 2147483647;
            wsHttpBinding.BypassProxyOnLocal = wsHttpBinding.AllowCookies = wsHttpBinding.TransactionFlow = false;
            wsHttpBinding.MessageEncoding = WSMessageEncoding.Text;
            wsHttpBinding.TextEncoding = Encoding.UTF8;
            wsHttpBinding.UseDefaultWebProxy = true;
            wsHttpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
            wsHttpBinding.ReaderQuotas = new XmlDictionaryReaderQuotas(); //ReaderQuotas, setting to Max
            wsHttpBinding.ReaderQuotas.MaxArrayLength = wsHttpBinding.ReaderQuotas.MaxBytesPerRead = 2147483647;
            wsHttpBinding.ReaderQuotas.MaxStringContentLength = wsHttpBinding.ReaderQuotas.MaxNameTableCharCount = 2147483647;
            wsHttpBinding.ReaderQuotas.MaxDepth = 2147483647;
            //Create the Proxy
            ChannelFactory<T> proxy = new ChannelFactory<T>(wsHttpBinding, endpointAddress);
            //Sets the MaxItemsInObjectGraph, so that client can receive large objects
            foreach (var operation in proxy.Endpoint.Contract.Operations)
            {
                DataContractSerializerOperationBehavior operationBehavior = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
                //If DataContractSerializerOperationBehavior is not present in the Behavior, then add
                if (operationBehavior == null)
                {
                    operationBehavior = new DataContractSerializerOperationBehavior(operation);
                    operation.Behaviors.Add(operationBehavior);
                }
                //IMPORTANT: As 'operationBehavior' is a reference, changing anything here will automatically update the value in list, so no need to add this behavior to behaviorlist
                operationBehavior.MaxItemsInObjectGraph = 2147483647;
            }
            return proxy;
        }

当我尝试编译时,我得到两个错误:

错误1 'Proxy<…>:不能在静态类中声明实例成员

错误3类型或命名空间名称'T'无法找到(您是否缺少using指令或程序集引用?)

为了使用ChannelFactory类,我遗漏了什么?

编辑:

我已将ChannelFactory更改为ChannelFactory,但现在我收到以下错误:

错误1 'Proxy<…>:不能在静态类中声明实例成员

以编程方式创建WCF客户端

Error   1   'Proxy<...>': cannot declare instance members in a static class

查看这个方法所在的类,并确保它不是static

Error   3   The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)

当您看到泛型类(如ChannelFactory<T>List<T>)的定义时,T只是实际类型(如List<string>List<DateTime>)的占位符。从上面的代码来看,我猜它是ChannelFactory<IReportData>


这是一个非常简单的客户端。我使用的示例服务是在创建新的WCF应用程序项目时创建的。

public class MyServiceClient : ClientBase<IService>, IService
{
    public string GetData(int value)
    {
        return base.Channel.GetData(value);
    }
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        return base.Channel.GetDataUsingDataContract(composite);
    }
}

来自ChannelFactory的文档:

通用的ChannelFactory类是高级使用的需要创建通道工厂的场景可以用于创建多个通道。

换句话说,如果你只是想创建一个客户端,那么你可能不需要使用ChannelFactory


在实践中,我使用Castle Windsor WCF Integration Facility来创建我的WCF客户机。这只适用于你对使用依赖注入和Castle Windsor感兴趣的情况。我强烈建议学习使用它,因为依赖注入是一种有用的实践。但除此之外,您还可以方便地使用它来创建和处置您的客户机。

结果是你的类永远不会"知道"WCF服务。他们只知道他们在使用IReportData。他们不知道该接口的实现是一个WCF客户端。在幕后,Windsor正在创建和处理客户端,在大多数情况下,唯一的配置是app.config中的一行<endpoint>元素。

这是他们文档的入口页