3

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

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

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

这就是我想做的事情:

class ItemResponse
{
    public bool Success { get; set; }
    public T Data{ get; set; }
}

if( /*acceptance criteria*/ )
{
    ItemResponse<SuccessData> resp = new ItemResponse<SuccessData>();
    resp.Data = new SuccessData();
}
else
{
    ItemResponse<ErrorData> resp = new ItemResponse<ErrorData>();
    resp.Data = new ErrorData();
}

return resp;


public class SuccessData
{

}

public class ErrorData
{

}

然后让 web 方法返回具有通用属性的对象。

这是否可能,如果是这样,鉴于必须正确输入 webmethod 返回类型,我该怎么做?

4

2 回答 2

4

泛型是在编译时添加类型安全的工具。因此,类的使用者使用的具体类型必须在编译时知道。如果你创建一个函数

List<T> myFunction<T>() {...}

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

var myResult = myFunction<int>();

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

但是,您希望在Data处确定的泛型类型run-time:如果发生错误,则返回一个ItemResponse<SuccessData>,否则返回一个ItemResponse<ErrorData>。这不是泛型的工作方式。

于 2013-04-16T13:59:41.083 回答
2

短版,你不能按照你的建议去做。

长(er)版本 A 部分

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

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

此伪代码等同于您尝试创建的代码,这就是编译器不允许它的原因。它不知道您要呼叫哪个。 DoSomething()

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

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

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

class Response
{
     public Collection<someType> Data;
}

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

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


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

class myResponse
{
    public SuccessResponse myRespData;
    public ErrorResponse myError
}

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


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

class Response
{
    public List<IYourData> 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 可以处理该特定方面。

于 2013-04-16T13:40:22.717 回答