WCF OperationContract - 应该公开哪种通用集合类型?

10

我有一个返回泛型集合的WCF Web服务方法。现在,我的问题是:我应该将其公开为ICollection<T>List<T>IList<T>IEnumerable<T>或其他什么?

我认为List<T>不可取,因为我想避免CA1002错误,但底层类型将是List<T>

我真的很想听听你们的意见,最好能够好好解释一下你们的想法。

谢谢提前。

2个回答

18

请注意,例如 CA1002 这样的错误实际上是针对库而言的。WCF 服务不是一个库,而是通过 SOAP、REST 等序列化所有内容的终结点。

如果您尝试公开 ICollection<T> 或 IList<T> 等接口,您将发现会出现无法序列化该类型的错误。实际上,在这里使用 List<T> 可能是最好的选择。当代理在客户端生成时,默认情况下它会成为一个数组,但许多人会将其更改为 List<T>,因此无论您如何选择公开它,90% 的时间内客户端将看到的仍然是这种类型。

我要注意的是,从 WCF 操作或 Web 服务中根本不返回集合通常是很好的做法。更常见的做法是创建一个包含所需集合的代理类并返回它,例如:

[OperationContract]
OrdersResult GetOrders(OrderRequest request);

代理类可能看起来像这样:

[DataContract]
public class OrdersResult
{
    [DataMember]
    public List<Order> Orders { get; set; }
}

这样,如果您决定需要向请求或响应添加更多数据,您可以这样做而不会对客户端造成破坏性的变化。


附加说明:WCF 的真正问题在于 WCF 不知道特定类型仅用于出站数据。 当通过 WCF 服务公开任何类时,WCF 假定它可以是请求或响应的一部分,如果它是请求的一部分,则类型 必须是具体的 并且不能是不可变的。 这就是为什么有所有其他愚蠢的限制,例如要求属性设置器的原因。

在这里,您只有使用具体的、可变的集合类型的选择,并且在大多数情况下,这意味着数组或泛型列表。


6
在我看来,暴露序列的服务和数据契约应明确表明这些序列是不可变的,因为它们作为DTO通过网络传输。在一个从不同层次接收到的序列上添加和删除并没有太多意义,相反,您希望读取该数据并执行某些操作。
鉴于这一点,我真的更喜欢使用IEnumerable,但不幸的是,在WCF中这并不适用很好。你可能会遇到各种奇怪的错误,特别是当涉及延迟执行时,所以(在WCF上下文中)最好远离它们。
这实际上只剩下数组了,因为它们在剩余选项中最能传达意图。

同意不可变性的部分,尽管数组并不比通用列表更不可变;只有大小是不可变的。 - Aaronaught
1
是的,我知道,这就是为什么我更喜欢使用IEnumerable的原因,但鉴于这不是一个选项,我们必须选择次优解。数组比列表仍然“更不可变”,因为您无法更改其大小,因此它们可以更清晰地传达意图...但是并没有太大区别,我承认 :) - Mark Seemann
1
哈哈,“更加不可变”。我猜这是一个很好的解释。 :P - Aaronaught

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接