如何返回具有通用属性的C#Web服务?

我正在创建一个Web服务,并希望使用返回数据更优雅,而不是拥有消费者需要检查的许多属性。

根据幕后生成的数据,我需要能够返回错误数据或消费者期望的数据。

我不想拥有一个大的扁平对象,并在需要时填充属性,并让用户检查“成功”标志,我希望单个属性Data可以是错误类的实例,也可以是一个成功的阶级。

这就是我想要做的事情:

class ItemResponse { public bool Success { get; set; } public T Data{ get; set; } } if( /*acceptance criteria*/ ) { ItemResponse resp = new ItemResponse(); resp.Data = new SuccessData(); } else { ItemResponse resp = new ItemResponse(); resp.Data = new ErrorData(); } return resp; public class SuccessData { } public class ErrorData { } 

然后让web方法返回带有generic属性的对象。

这是否可能,如果是这样,我将如何做,因为必须正确输入webmethod返回类型?

generics是在编译期间添加类型安全性的工具。 因此,必须在编译时知道类的使用者使用的具体类型。 如果您创建一个function

 List myFunction() {...} 

…然后你需要在调用时指定T ,例如

 var myResult = myFunction(); 

…这使得在编译时知道具体类型。 (即使你没有指定T因为它可以被推测,具体类型在编译时也是已知的。)

但是,您希望在run-time确定通用类型的Data :如果发生错误,则返回ItemResponse ,否则返回ItemResponse 。 这不是generics如何工作。

简短的版本 ,你不能做你所建议的,因为你已经奠定了它。

长(呃)版本 A部分

Web服务可以被视为类的方法,实际上 Web服务类的一种方法。 我建议阅读一些Web服务教程,以便更好地掌握设置Web服务背后的机制。 MSDN有许多Microsoft堆栈特定的教程,可以使用您最喜欢的搜索引擎轻松找到。

方法的返回对象不允许具有多态行为,这基本上就是您的要求。

这个伪代码等同于您尝试创建的代码,这就是编译器不允许的原因。 它不知道你试图打电话给哪个 DoSomething()

 class myFoo { public SuccessResponse DoSomething() {....} public ErrorResponse DoSomething() {....} } 

或者,您可以设想这样的事情:
public [SuccessResponse | ErrorResponse] DoSomething()
但那也应该是显而易见的原因。 C#根本不支持多态返回。

B部分即使我们只关注resp.Data ,该对象仍然必须被声明为某种类型。

 class Response { public Collection Data; } 

如果您的SuccessDataErrorData实现相同的接口,那么someType可能只是IyourInterface但这引发了另一个问题。 也就是说,最终用户将如何知道他们是否在Data中获得了良好的数据,或者是否存在隐藏在其中的错误响应。

我相信,只要您将它声明为WCF服务对象的公共部分,WCF就足以为您序列化IyourInterface 。 但这仍然无法解决最终用户如何知道该怎么做。


如果你愿意在响应中不那么优雅,那么经典模式就是简单地将你的成功数据和错误对象捆绑到另一个响应类中,如下所示:

 class myResponse { public SuccessResponse myRespData; public ErrorResponse myError } 

现在,最终用户检查他们是否关心是否有错误。 假设没有错误,那么他们会去查看响应数据。


根据您的评论,是的,您也可以执行以下操作:

 class Response { public List Data; public YourEnum ReturnType; } public class ResponseData : IYourData { ... } public class ErrorData : IYourData { ... } 

然后在客户端上,您可以执行以下简单检查:

 if( ReturnType == YourEnum.Success ) { ... } else if( ReturnType == YourEnum.Error ) { ... } else ... 

WCF将为您处理List的序列化。 它将转换为数组或直接传递集合,具体取决于您所使用的设置。 有一些SO Q&A可以处理这个特定的方面。