WCF - 序列化继承类型

发布于 2024-08-23 05:18:28 字数 866 浏览 7 评论 0原文

我有这些类:

[DataContract]
public class ErrorBase {}

[DataContract]
public class FileMissingError: ErrorBase {}

[DataContract]
public class ResponseFileInquiry
{
  [DataMember]
  public List<ErrorBase> errors {get;set;};
}

ResponseFileInquiry 类的实例是我的服务方法返回给客户端的内容。现在,如果我用 ErrorBase 的实例填充 ResponseFileInquiry.errors,一切正常,但如果我添加继承类型 FileMissingError 的实例,我会在序列化期间收到服务端异常:

Type 'MyNamespace.FileMissingError' with data contract name 'FileMissingError' 
is not expected. Add any types not known statically to the list of known types - 
for example, by using the KnownTypeAttribute attribute or by adding them to the 
list of known types passed to DataContractSerializer.'

因此序列化程序会感到困惑,因为它期望列表包含声明的类型对象 (ErrorBase) 但它正在获取继承类型 (FileMissingError) 对象。

我有一大堆错误类型,列表将包含它们的组合,那么我该怎么做才能使它工作呢?

I have these classes:

[DataContract]
public class ErrorBase {}

[DataContract]
public class FileMissingError: ErrorBase {}

[DataContract]
public class ResponseFileInquiry
{
  [DataMember]
  public List<ErrorBase> errors {get;set;};
}

An instance of the class ResponseFileInquiry is what my service method returns to the client. Now, if I fill ResponseFileInquiry.errors with instances of ErrorBase, everything works fine, but if I add an instance of inherited type FileMissingError, I get a service side exception during serialization:

Type 'MyNamespace.FileMissingError' with data contract name 'FileMissingError' 
is not expected. Add any types not known statically to the list of known types - 
for example, by using the KnownTypeAttribute attribute or by adding them to the 
list of known types passed to DataContractSerializer.'

So serializer is getting confused because it's expecting the List to contain the declared type objects (ErrorBase) but it's getting inherited type (FileMissingError) objects.

I have the whole bunch of error types and the List will contain combinations of them, so what can I do to make it work?

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

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

发布评论

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

评论(3

夜还是长夜 2024-08-30 05:18:28

您应该将 KnownType 属性添加到基类中

[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}

在此 博客

You should add KnownType attribute to your base class

[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}

Read more about KnownType attribute in this blog

路还长,别太狂 2024-08-30 05:18:28

试试这个:

[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}

正如错误消息所述,任何无法静态了解的信息(例如您在此处表达的多态关系)都必须通过属性提供。在这种情况下,您需要指定您的 FileMissingError 数据协定是其基类 ErrorBase 的已知类型。

Try this:

[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}

As the error message states, any information that cannot be know statically (like the polymorphic relationship you have expressed here) must be supplied via attributes. In this case you need to specify that your FileMissingError data contract is a known type of its base class, ErrorBase.

音栖息无 2024-08-30 05:18:28

有点晚了,但也许对于后代来说。 =)

如果您不想为父类的每个子类添加属性,您可以使用父类静态构造函数构造已知类型的列表,

 IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain
                                             .GetAssemblies()
                                             .Where(a => !a.GlobalAssemblyCache);

 IEnumerable<Type> serializableTypes = assemblies.SelectMany(a => a.GetTypes())
                                                 .Where(t => IsSerializable(t));

// ...

private static bool IsSerializable(Type type)
{
    return type.GetCustomAttributes(true).Any(a => a is DataContractAttribute);
}

并将该列表传递给 de/serializers 构造函数。我不知道这个解决方案有多强大,但这就是我正在做的事情,到目前为止它是有效的。它有点慢,所以一定要缓存结果。

A tad bit late, but maybe for future generations. =)

If you don't want to add an attribute for every child class to your parent class, you could construct a list of known types in the parent classes static constructor using

 IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain
                                             .GetAssemblies()
                                             .Where(a => !a.GlobalAssemblyCache);

 IEnumerable<Type> serializableTypes = assemblies.SelectMany(a => a.GetTypes())
                                                 .Where(t => IsSerializable(t));

// ...

private static bool IsSerializable(Type type)
{
    return type.GetCustomAttributes(true).Any(a => a is DataContractAttribute);
}

and pass this list to the de/serializers constructor. I don't know how robust this solution is, but that's what I am doing and so far it works. It is a little slow, so make sure to cache the result.

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