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