15

我有这些课程:

[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.'

所以序列化程序变得困惑,因为它期望 List 包含声明的类型对象(ErrorBase),但它正在获取继承的类型(FileMissingError)对象。

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

4

3 回答 3

17

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

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

在此博客中阅读有关 KnownType 属性的更多信息

于 2010-02-24T21:01:21.753 回答
7

尝试这个:

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

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

于 2010-02-24T21:00:29.107 回答
2

有点晚了,但也许是为了后代。=)

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

 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 构造函数。我不知道这个解决方案有多强大,但这就是我正在做的事情,到目前为止它有效。它有点慢,因此请确保缓存结果。

于 2012-10-23T14:19:02.533 回答