6

我想知道如何在 WCF 中配置已知类型。例如,我有一个Person类和一个Employee类。Employee类是Person类的子类。两个类都标有一个[DataContract]属性。

我不想硬编码类的已知类型,例如[ServiceKnownType(typeof(Employee))]在 Person 类中放置一个,以便 WCF 知道 Employee 是 Person 的子类。

现在,我在主机的 App.config 中添加了以下 XML 配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Person, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
          <knownType type="Employee, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral, PublicKeyToken=null" />
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
  <system.serviceModel>
    ....... 
  </system.serviceModel>
</configuration>

我编译它,运行主机,在客户端添加服务引用并添加一些代码并运行客户端。但是出现了错误:

格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数时出现错误 http://www.herbertsabanal.net:person。InnerException 消息是“第 1 行位置 247 中的错误。元素 'http://www.herbertsabanal.net:person' 包含 'http://www.herbertsabanal.net/Data:Employee' 数据合同的数据。反序列化器不知道映射到该合约的任何类型。将与 'Employee' 对应的类型添加到已知类型列表中 - 例如,通过使用 KnownTypeAttribute 属性或将其添加到传递给 DataContractSerializer 的已知类型列表中。有关更多详细信息,请参阅 InnerException。

以下是数据合同:

[DataContract(Namespace="http://www.herbertsabanal.net/Data", Name="Person")]
    class Person
    {
        string _name;
        int _age;

        [DataMember(Name="Name", Order=0)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember(Name="Age", Order=1)]
        public int Age
        {
            get { return _age; }
            set { _age = value; }
        }
    }


[DataContract(Namespace="http://www.herbertsabanal.net/Data", Name="Employee")]
    class Employee : Person
    {
        string _id;

        [DataMember]
        public string ID
        {
            get { return _id; }
            set { _id = value; }
        }
    }

顺便说一句,我的服务没有使用类库(WCF 类库或非 WCF 类库)。我只是在宿主项目中对其进行了简单的编码。

我想配置文件肯定有问题(请参阅上面的配置文件)。或者我一定错过了什么。任何帮助将不胜感激。

4

3 回答 3

8

我想我现在已经找到了答案。

我在上面发布的配置文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Person, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
          <knownType type="Employee, WCFWithNoLibrary, Version=1.0.0.0,Culture=neutral, PublicKeyToken=null" />
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
  <system.serviceModel>
    ....... 
  </system.serviceModel>
</configuration>

我刚刚添加的是Person类和Employee类的命名空间。并且不需要更长的 Version 和 Culture 值......正确的配置应该是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="WCFWithNoLibrary.Person, WCFWithNoLibrary">
          <knownType type="WCFWithNoLibrary.Employee, WCFWithNoLibrary" />
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
  <system.serviceModel>
    ....... 
  </system.serviceModel>
</configuration>

现在它更短,更有意义。但如果使用 3rd 方库,则需要添加版本、文化、publickeytokens。

于 2009-02-18T08:53:15.657 回答
6

我知道这是很久以前回答的,但是,另一个(对于未来的程序员可能更明显)解决方案:

[KnownType(typeof(SubClass))]
public class BaseClass

斯科特

于 2011-03-17T14:46:43.627 回答
0

在另一种情况下,我也收到了这个冗长的错误消息。我确实使用KnownTypeAttribute并成功部署了一个WCF.RIA用于生产的应用程序。在第二个版本中,我添加了一个新的子类型,并添加了必要的对应KnownTypeAttribute(编译器不接受没有这个属性 - 很好)。但是,编译器接受的内容以及在我的机器上运行的内容并没有在生产中运行。只有在生产中我才得到上面提到的错误。比较现有子类型和新子类型的所有用法,我发现我忘记了WCF.RIA需要在方法名称中使用子类型的名称,例如 GetMySubTypes。因此,如果在添加属性后出现此错误,请查看是否是因为WCF.RIAs 约定。

于 2011-04-21T14:23:30.193 回答