如何重写 WCF 客户端以使用 ChannelFactory 而不是服务引用 [英] How to re-write WCF client to use ChannelFactory instead of service reference

查看:46
本文介绍了如何重写 WCF 客户端以使用 ChannelFactory 而不是服务引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 网络服务软件工厂创建的 WCF 服务.我所有传入的请求和返回的响应都是作为消息契约实现的.我一直在通过在 VS 中添加服务引用来访问该服务,该服务运行良好.但是,我现在被告知这不是标准的公司方式,我需要使用基于 System.ServiceModel.ChannelFactory 的内部 WCF 代理助手类来调用服务.

I have a WCF service created using the web service software factory. All my incoming requests and returned responses are implemented as message contracts. I had been accessing the service by adding a service reference in VS which worked fine. However I've now been told that this isn't the standard company way and that I need to call the service using an in-house WCF proxy helper class based on the System.ServiceModel.ChannelFactory.

我以前从未使用过 ChannelFactory,我正在努力找出重写客户端访问的最佳方法.服务契约由服务工厂生成,我需要为代理助手类提供服务接口.这是服务合同的一部分 - 该服务总共有大约 25 个操作:

I've never used the ChannelFactory before and I'm struggling to figure out the best way to re-write the client access. The service contract is generated by the service factory and I need to provide the service interface to the proxy helper class. Here's part of the service contract - there's about 25 operations in total on the service:

namespace CAEWCFService.ServiceContracts
{
  /// <summary>
  /// Service Contract Class - CAEServiceContract
  /// </summary>
  [WCF::ServiceContract(Namespace = "urn:CAEServiceServiceContracts", Name = "CAEServiceContract", SessionMode = WCF::SessionMode.Allowed, ProtectionLevel = ProtectionLevel.None )]
  public partial interface ICAEServiceContract 
  {
    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "GetAllIncomes", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllIncomesReponse GetIncomeRecords(CAEService.MessageContracts.GetAllIncomesRequest request);

    [WCF::OperationContract(IsTerminating = false, IsInitiating = true, IsOneWay = false, AsyncPattern = false, Action = "urn:CAEServiceServiceContracts.CAEServiceContract.GetSecurityRecords", ProtectionLevel = ProtectionLevel.None)]
    CAEService.MessageContracts.GetAllSecuritiesResponse GetSecurityRecords(CAEService.MessageContracts.GetAllSecuritiesRequest request);

    //... the rest
  }
}

这是来自客户端的调用 GetIncomeRecords 操作的调用:

And here's the call from the client side calling the GetIncomeRecords operation:

CAEServiceContractClient client = new CAEServiceContractClient();    

IncomeSearchItem item = new IncomeSearchItem()
{
    aCode = aCode.Text,
    bCode = bCode.Text,
    sCode = sCode.Text,
    secDesc = tbSecurityName.Text,
    status = statusValue != 0 ? statusValue : 0,
    fromDate = fromDate,
    toDate = toDate,
    IncomeID = 0,
    userBank = userBank,
    userId = userId,
    currentRate = currentSourceVal != 0 ? currentSourceVal : 0,
    dateConfirmed = ddDate.SelectedValue,
    pageIndex = pageIdx,
    pageSize = recordsPerPage
};

GetAllIncomesReponse response = new GetAllIncomesReponse();

try
{
    response = client.GetIncomeRecords(item);
    totalRecords = response.TotalRecords;

    incomelist.DataSource = response.IncomeItemColl;
    incomelist.DataBind();

    //.. the rest
}

这是来自另一个项目的一些示例代码,展示了如何使用代理助手.我的服务的问题在于它期望并返回消息协定,而示例传递原始类型并返回原始类型或数据集:

Here's some sample code from another project showing how to use the proxy helper. The problem with my service is that it expects and returns message contracts whereas the sample one passes in primitive types and returns primitives or datasets:

public static class ServiceHelper
{
  /// <summary>
  /// Services the verification.
  /// </summary>
  /// <param name="user">The user.</param>
  /// <returns></returns>
  public static string ServiceVerification(string user)
  {
    return WCFProxyHelper<IFCAServices>.Use(client =>
      client.ServiceVerification(user));
  } 
}

那么最快/最简单的方法是什么?如何让 ChannelFactory 知道我的 IncomeSearchItem 和我需要传递给服务的其他几个对象?我可以/应该使用 svcutil 来生成所有对象并在 ChannelFactory 中使用它吗?

So what's the quickest / easiest way to do this? How do I make the ChannelFactory aware of my IncomeSearchItem and several other objects that I need to pass to the service? Can / should I use svcutil to generate all the objects and use that in the ChannelFactory?

推荐答案

你是说公司方式"是使用服务助手,还是说它内部基于ChannelFactory创建代理——或者,你想创建您自己的代理类很长的路要走.这对你有用吗?ServiceHelper 上的扩展方法可以让您继续使用公司方式,但不需要更改 ServiceHelper 以了解您的请求/响应消息或它们包含的任何内容.

Are you saying that the "Company Way" is to use the service helper, and that it internally creates a proxy based on ChannelFactory - or, do you want to create your own proxy class the long way. Would this work for you? An extension method on ServiceHelper would let you stay using the company way, but would not require the ServiceHelper to be changed to know about your request/response messages or anything they contain.

using CAEService;
using CAEService.MessageContracts;

public static class ServiceHelperExtensions
{
    public static GetAllIncomesReponse GetIncomeRecords(this ServiceHelper, GetAllIncomesRequest request)
    {
        return WCFProxyHelper<ICAEServiceContract>.Use(client =>
            client.GetAllIncomes(request));
    }
}

然后在客户端代码中,您将替换为:

Then in client code, you would replace this:

 response = client.GetIncomeRecords(item);

这样:

response = ServiceHelper.GetIncomeRecords(item);

我认为您还必须使用 SVCUTIL.exe 命令来生成代理类,然后编辑结果以去除代理并仅保留请求/响应类及其支持类型.或者,如果您已经在 VS 中完成了添加服务引用",则可以单击解决方案资源管理器中的显示所有文件"选项并深入查看服务引用.其中一个文件包含生成的服务代理及其支持类型,全部在一个文件中.

I think you will also have to use the SVCUTIL.exe command to generate a proxy class, and then edit the result stripping out the proxy and leaving only the request/response classes and their supporting types. Alternatively, if you have already done "Add Service Reference" in VS, you can click the "Show All Files" option in solution explorer and drill into the service reference. One of those files contains the generated service proxy and its supporting types, all in one file.

这篇关于如何重写 WCF 客户端以使用 ChannelFactory 而不是服务引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆