如何在WCF中接受基本类型的集合 [英] How to accept a collection of a base type in WCF

查看:77
本文介绍了如何在WCF中接受基本类型的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置

我有一个WCF服务,它公开了基本类型(例如Animal)以及一些派生类型(例如狮子,老虎和熊)。另一种类型(例如Zoo)包括一个属性,该属性是基本类型的集合。基本类型是具体的,不是抽象的,因此对于集合包含基本类型和/或派生类型的实例(以任何组合)是完全可以接受的。例如:

I have a WCF service that exposes a base type (e.g. Animal) as well as a few derived types (e.g. Lion, Tiger, and Bear). Another type (e.g. Zoo) includes a property that is a collection of the base type. The base type is concrete, not abstract, so it is perfectly acceptable for the collection to contain instances of the base type and/or the derived types (in any combination). For example:

[DataContract, KnownType(typeof(Lion)),
KnownType(typeof(Tiger)), KnownType(typeof(Bear))]
public class Animal
{
    [DataMember]
    public string Species { get; set; }
}

[DataContract]
public class Lion : Animal { }


[DataContract]
public class Tiger : Animal { }


[DataContract]
public class Bear : Animal { }

[DataContract]
public class Zoo 
{
    [DataMember]
    public List<Animal> Animals { get; set; }
}

我的服务操作之一接受此类型作为其参数,例如:

One of my service operations accepts this type as its parameter, like so:

[ServiceContract]
public interface IZooService
{
    [OperationContract]
    void SetZoo(Zoo zoo);
}

所有这些都很好,并且发出的WSDL看起来非常合适我。它包含所有类型,并正确指示派生类型是从基本类型继承的。因此,我应该能够使用如下的SOAP消息来调用我的服务:

All of this is well and good, and the emitted WSDL looks perfectly fine to me. It contains all of the types and correctly indicates that the derived types inherit from the base type. So, I should be able to call my service using a SOAP message such as the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:z="http://zoo.org">
   <soapenv:Header/>
   <soapenv:Body>
      <z:SetZoo>
         <z:Zoo>
            <z:Animals>
               <z:Animal>
                  <z:Species>Crocodile</z:Species>
               </z:Animal>
               <z:Tiger>
                  <z:Species>Bengal</z:Species>
               </z:Tiger>
               <z:Bear>
                  <z:Species>Grizzly</z:Species>
               </z:Bear>
            </z:Animals>
         </z:Zoo>
      </z:SetZoo>
   </soapenv:Body>
</soapenv:Envelope>

在上面的SOAP消息中,动物集合包含基本动物类型的一个实例,派生的Tiger类型,以及派生的Bear类型的实例。 WCF应该能够成功反序列化此消息。

In the above SOAP message, the Animals collection contains one instance of the base Animal type, an instance of the derived Tiger type, and an instance of the derived Bear type. WCF should be able to deserialize this message successfully.

问题

WCF收到以上消息时不会抛出任何异常。相反,它只是完全忽略了派生类型(老虎和熊),在反序列化消息传递到我的代码时,动物类集合只包含鳄鱼条目,因为它是基本类型。

WCF doesn't throw any exceptions when it receives the above message. Instead, it simply ignores the derived types (Tiger and Bear) completely, and by the time deserialized message is passed to my code, the Animals collection only contains the Crocodile entry, since it is of the base type.

所以,我想我有两个问题...首先,为什么WCF不对集合中的派生类型实例进行反序列化。其次,由于WCF显然不喜欢此SOAP消息,为什么它不引发异常?这种无声的故障非常令人困扰。

So, I guess I have two questions... First, why is WCF not deserializing the derived type instances in the collection. And second, since WCF obviously doesn't like something about this SOAP message, why isn't it throwing an exception? This sort of silent failure is very troubling.

推荐答案

好吧...我知道了问题所在。事实证明,此方案的SOAP语法需要一些额外的工作才能正确完成。因为Animals集合被定义为Animal类型的数组,所以SOAP消息中的所有子元素都必须是元素,即使它们实际上是派生类型的实例也是如此。实际的实例类型由 type属性定义,该属性是XMLSchema-instance命名空间的一部分。因此,我的SOAP消息应该看起来像这样:

Okay... I figured out the problem. It turns out that the SOAP syntax for this scenario requires a little extra work to get right. Because the Animals collection is defined as an array of Animal types, all of the child elements in the SOAP message need to be elements, even if they are actually instances of a derived type. The actual instance type is defined by the "type" attribute, which is part of the XMLSchema-instance namespace. So, my SOAP message should have looked like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://zoo.org">
<soapenv:Header/>
<soapenv:Body>
  <z:SetZoo>
     <z:Zoo>
        <z:Animals>
           <z:Animal>
              <z:Species>Crocodile</z:Species>
           </z:Animal>
           <z:Animal i:type="z:Tiger">
              <z:Species>Bengal</z:Species>
           </z:Animal>
           <z:Animal i:type="z:Bear">
              <z:Species>Grizzly</z:Species>
           </z:Animal>
        </z:Animals>
     </z:Zoo>
  </z:SetZoo>
</soapenv:Body>
</soapenv:Envelope>

当然,这仍然没有解决我的另一个问题,那就是WCF反序列化器应该抛出如果它不理解SOAP消息,则为异常。它不应该只是默默地忽略部分消息!

Of course, that still doesn't address my other concern, which is that the WCF deserializer should throw an exception if it doesn't understand the SOAP message. It shouldn't just silently ignore parts of the message!

这篇关于如何在WCF中接受基本类型的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆