我有这些课程:
[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)对象。
我有一大堆错误类型,List会包含它们的组合,那么我该怎么做才能使它工作?
答案 0 :(得分:17)
您应该将KnownType属性添加到基类
[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}
详细了解此blog
中的KnownType属性答案 1 :(得分:7)
试试这个:
[DataContract]
[KnownType(typeof(FileMissingError))]
public class ErrorBase {}
正如错误消息所述,任何无法静态知道的信息(如此处表达的多态关系)必须通过属性提供。在这种情况下,您需要指定您的FileMissingError
数据协定是其基类的已知类型ErrorBase
。
答案 2 :(得分: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构造函数。我不知道这个解决方案有多强大,但这就是我正在做的事情,到目前为止它的工作原理。它有点慢,所以一定要缓存结果。