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

时间:2013-04-16 13:12:51

标签: c# web-services generics

我正在创建一个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返回类型?

2 个答案:

答案 0 :(得分:4)

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

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

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

var myResult = myFunction<int>();

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

但是,您希望Data确定通用类型run-time:如果发生错误,则返回ItemResponse<SuccessData>,否则返回ItemResponse<ErrorData>。这不是泛型如何运作。

答案 1 :(得分:2)

简短版,你不能按照自己的意思行事。

长(呃)版本 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<someType> Data;
}

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

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


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

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&amp; A处理这个特定的方面。