如何重写WCF客户端以使用ChannelFactory而不是服务引用

时间:2011-03-29 07:59:43

标签: wcf wcf-client

我使用web service software factory创建了一个WCF服务。我的所有传入请求和返回的响应都作为消息合同实现。我通过在VS中添加服务引用来访问该服务,该工作正常。但是我现在被告知这不是标准的公司方式,我需要使用基于System.ServiceModel.ChannelFactory的内部WCF代理帮助程序类来调用该服务。

我之前从未使用过ChannelFactory,而且我正在努力找出重写客户端访问权限的最佳方法。服务工厂生成服务合同,我需要为代理帮助程序类提供服务接口。这是服务合同的一部分 - 该服务共有约25项操作:

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操作的调用:

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
}

以下是另一个项目的示例代码,展示了如何使用代理帮助程序。我的服务的问题是它期望并返回消息契约,而样本传递基本类型并返回基元或数据集:

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中使用它吗?

1 个答案:

答案 0 :(得分:1)

您是说“公司方式”是使用服务帮助程序,并且它在内部创建基于ChannelFactory的代理 - 或者,您是否希望长期创建自己的代理类。这对你有用吗? ServiceHelper上的扩展方法可以让您继续使用公司方式,但不需要更改ServiceHelper以了解您的请求/响应消息或它们包含的任何内容。

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

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

 response = client.GetIncomeRecords(item);

用这个:

response = ServiceHelper.GetIncomeRecords(item);

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