以编程方式创建WCF客户端

时间:2016-06-30 02:31:19

标签: c# wcf

我正在运行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上找到的以下代码片段。

我找到的帖子的链接是:Configure wcf service programmatically

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'代理&lt; ...&gt;':无法在静态类中声明实例成员

  

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

为了使用ChannelFactory类,我缺少什么?

编辑:

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

  

错误1'代理&lt; ...&gt;':无法在静态类中声明实例成员

1 个答案:

答案 0 :(得分:2)

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>或{{1} }。从上面的代码看,我猜它是List<DateTime>

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

ChannelFactory<IReportData>

来自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); } } 的{​​{3}}:

  

通用的ChannelFactory类用于高级   需要创建可以的渠道工厂的方案   用于创建多个频道。

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

实际上,我使用documentation来创建我的WCF客户端。这只适用于您对使用依赖注入和使用Castle Windsor感兴趣的情况。我强烈建议学习使用它只是因为依赖注入是一种有用的做法。但除此之外,您还可以方便地使用它来创建和部署您的客户。

结果是您的类永远不会“知道”有关WCF服务的信息。他们只知道他们正在使用ChannelFactory。他们不知道该接口的实现是WCF客户端。在幕后,Windsor正在创建和部署客户端,在大多数情况下,唯一的配置是app.config中的单行IReportData元素。

以下是他们文档的Castle Windsor WCF Integration Facility