如何在WCF中一般执行服务操作?

时间:2010-01-10 18:20:22

标签: wcf messagecontract

我正在寻找一种方法来完成下面源代码中说明的行为。我使用“始终生成消息合同”选项创建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,并且它可以自动神奇地工作。

2 个答案:

答案 0 :(得分: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打算工作的方式 - 不能保证你真的能够把它拉下来。

答案 1 :(得分: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));
    }
}