以编程方式创建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<…>:不能在静态类中声明实例成员
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>
元素。
这是他们文档的入口页