2

我正在寻找一种方法来完成下面源代码中所示的行为。我使用“始终生成消息合同”选项创建了 WCF 服务代理。我所有的请求和响应消息合约都实现了一个通用接口,我想使用相同的函数来执行它们。在我看来,应该有一种通过客户端代理发送消息的通用方式,但我在任何地方都找不到。任何帮助将不胜感激!

// I can do this
private IPagedResponse GetAllFoods()
{
    NutrientDBClient client = new NutrientDBClient();
    GetAllFoodsRequest request = new GetAllFoodsRequest();
    GetAllFoodsResponse response = client.GetAllFoods(request);

    return response;
}
// I'd like to do this
private IPagedResponse ExecutePagedRequest(IPagedRequest request)
{
    NutrientDBClient client = new NutrientDBClient();
    IPagedResponse response = (IPagedResponse)client.Execute(request);

    return response;
}

我目前在 NutrientDBClient 中添加了一个 ExecutePagedRequest(IPagedRequest) 方法,并根据 IPagedRequest 的具体类型手动执行正确的服务操作。我正在寻找一种更优雅的方式,以便我可以简单地在消息合约上实现 IPagedRequest 并且它会自动神奇地工作。

4

2 回答 2

2

不是 100% 确定您真正想要实现什么,但让我解释一下有关 WCF 的一些基础知识。

许多程序员错误地将 WCF 视为某种 .NET 远程处理 - 例如,他们认为您基本上是在访问远处服务器上的远程对象,在某处调用“远程”.NET 对象上的方法。绝对不是这样!

WCF 是关于消息传递的——您的客户端和服务器只交换序列化的消息(可能还有标头)——但仅此而已。

也就是说:这些消息交换机制旨在与许多非 .NET 平台——Java、Ruby——互操作。它们利用 WSDL 和 XSD 机制来交换操作描述 (WSDL) 和正在交换的数据结构 (XSD)。

WSDL 和 XSD 都是关于定义良好的显式调用和数据结构。这些标准提供的功能是所有 SOA 平台之间的最低公分母 - 因此,它比您可能已经习惯使用纯 .NET 的功能更受限制。SOA 世界和 OOP 世界并不总是很好地匹配。

所以最后,你真正需要理解和编程的是 WSDL/XSD 定义的标准——因此,你需要忘记所有 .NET 的细节,如泛型、接口和快速实现这些接口的类。它们根本无法通过 WCF 消息传递基础结构工作。

您可以在 WCF 客户端和 WCF 服务器之间交换的所有内容都是您可以在 XML 模式中描述和表达的任何内容——由字符串、整数等基本数据类型组成的具体类型。XSD 支持一点继承,但它不知道泛型,它根本不处理接口和非具体类。

因此,开箱即用,我认为您使用通用接口和实现该接口的消息和 WCF 确定基于该类调用的真正方法的方法不会奏效。这不是 WCF 的架构和设计方式。

您可能能够创建一个自定义(但具体的)基类,并且您可能能够扩展服务器端的 WCF 操作调度程序,以根据传入的类调用不同的方法(或标题中的一些额外信息来一路走来)——但我认为这既不容易,也不是 WCF 的工作方式——不能保证你真的能够成功。

于 2010-01-10T21:00:20.230 回答
0

下面是我如何解决这个问题。我的消息合同,实现 IPagedRequest 和 IPagedResponse。NutrientDBClient 是我的代码生成客户端代理 (ClientBase)。ExecutePagedRequest() 根据具体的请求类型进行消息路由。

public interface IPagedRequest
{
    PagingContext PageInfoState { get; set; }
}

public interface IPagedResponse
{
    PagingContext PageInfoState { get; }
    IEnumerable ResultItems { get; }
}

public partial class NutrientDBClient : IHasPagedServiceOperations
{
    public IPagedResponse ExecutePagedRequest(IPagedRequest request)
    {
        if (request == null) { throw new ArgumentNullException("request"); }

        if (typeof(GetAllFoodsRequest).IsAssignableFrom(request.GetType()))
        {
            return GetAllFoods((GetAllFoodsRequest)request);
        }

        // Other Service Operations that take IPagedRequest and 
        // return IPagedResponse removed for example


        throw new NotSupportedException(
            string.Format("Paged requests of type {0} are not supported.",
                request.GetType().Name));
    }
}
于 2010-01-11T13:08:27.713 回答