WCF:配置已知类型

jer*_*oft 6 wcf wcf-configuration

我想知道如何在WCF中配置已知类型.例如,我有一个Person类和一个Employee类.该员工类是的sublass 类.这两个类都标有[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>
Run Code Online (Sandbox Code Playgroud)

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

格式化程序在尝试反序列化消息时抛出异常:尝试反序列化参数时出错 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; }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

我猜配置文件一定有问题(请参阅上面的配置文件).或者我必须遗漏一些东西.任何帮助都会非常感激.

jer*_*oft 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>
Run Code Online (Sandbox Code Playgroud)

我刚刚添加的是Person类的Namespace 和Employee类.并且不需要更长的版本和文化值....正确的配置应该是:

<?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>
Run Code Online (Sandbox Code Playgroud)

现在它更短,更有意义.但是如果使用第三方库,则需要添加版本,文化,publickeytokens.

  • 给予好评.您是否必须在客户端.config上执行任何操作? (2认同)

Doo*_*Dah 6

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

[KnownType(typeof(SubClass))]
public class BaseClass
Run Code Online (Sandbox Code Playgroud)

斯科特

  • 如果子类型位于不同的项目中,则并非总是可行 (4认同)