WCF:配置已知类型

发布于 2024-07-14 07:42:05 字数 2494 浏览 11 评论 0原文

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

我不想对类的已知类型进行硬编码,例如在 Person 类中放置 [ServiceKnownType(typeof(Employee))] ,以便 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' 数据合同。 解串器没有 映射到的任何类型的知识 这份合同。 添加类型 对应于“员工” 已知类型列表 - 例如,通过 使用 KnownTypeAttribute 属性 或者将其添加到已知列表中 类型传递给 数据契约序列化器。'。 请参见 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 类库)。 我只是在宿主项目中对其进行了简单编码。

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

I want to know as to how to configure known types in WCF. For example, I have a Person class and an Employee class. The Employee class is a sublass of the Person class. Both class are marked with a [DataContract] attribute.

I dont want to hardcode the known type of a class, like putting a [ServiceKnownType(typeof(Employee))] at the Person class so that WCF will know that Employee is a subclass of Person.

Now, I added to the host's App.config the following XML configuration:

<?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>

I compiled it, run the host, added a service reference at the client and added some code and run the client. But an error occured:

The formatter threw an exception while
trying to deserialize the message:
There was an error while trying to
deserialize parameter
http://www.herbertsabanal.net:person.
The InnerException message was 'Error
in line 1 position 247. Element
'http://www.herbertsabanal.net:person'
contains data of the
'http://www.herbertsabanal.net/Data:Employee'
data contract. The deserializer has no
knowledge of any type that maps to
this contract. Add the type
corresponding to 'Employee' to the
list of known types - for example, by
using the KnownTypeAttribute attribute
or by adding it to the list of known
types passed to
DataContractSerializer.'. Please see
InnerException for more details.

Below are the data contracts:

[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; }
        }
    }

Btw, I didn't use class libraries (WCF class libraries or non-WCF class libraries) for my service. I just plain coded it in the host project.

I guess there must be a problem at the config file (please see config file above). Or I must be missing something. Any help would be pretty much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

灵芸 2024-07-21 07:42:05

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

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

<?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>

现在它更短并且更有意义。 但如果使用第三方库,则需要添加版本、文化、公钥令牌。

I guess I have found the answer now.

The configuration file I posted above looks like this:

<?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>

What I just added was, the Namespace of the Person class and the Employee class. And no need for the longer Version and Culture values.... The correct configuration should be:

<?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>

Now it is shorter and makes more sense. But if 3rd party libraries are used, then adding version, culture, publickeytokens would be required.

森末i 2024-07-21 07:42:05

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

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

Scott

I know this was answered a long time ago, but, another (maybe more obvious for future programmers) solution:

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

Scott

私藏温柔 2024-07-21 07:42:05

我在另一种情况下也收到了这个冗长的错误消息。 我确实使用了 KnownTypeAttribute 并成功地将使用 WCF.RIA 的应用程序部署到生产环境中。 在第二个版本中,我添加了一个新的子类型,并添加了必要的相应的 KnownTypeAttribute (如果没有这个属性,编译器不会接受它 - 太棒了)。 然而,编译器接受的内容以及在我的机器上运行的内容并未在生产中运行。 仅在生产中我才收到上述错误。 比较现有子类型和新子类型的所有用途,发现我忘记了 WCF.RIA 要求在方法名称中使用子类型的名称,例如 GetMySubTypes。 因此,如果您在添加属性后收到此错误,请查看是否是由于 WCF.RIA 约定所致。

I got this lengthy error message also in another case. I did use the KnownTypeAttribute and had successfully deployed an application which uses WCF.RIA to production. In the second release I added a new subtype, and added the necessary corresponding KnownTypeAttribute (the compiler did not accept it without this attribute - great). What the compiler did accept and what ran on my machine, did not run in production, however. Only in production I got the error mentioned above. Comparing all the uses of the existing subtypes and the new one revealed I had forgotten that WCF.RIA requires the name of the subtype to be used in a name of a method, like GetMySubTypes. So if you get this error after having added the attributes, see whether it's because of WCF.RIAs conventions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文