DataContract which includes Exception

本文关键字:Exception includes which DataContract | 更新日期: 2023-09-27 18:08:00

我有一个类(属性和一些方法)

[DataContract]
public partial class AbstractApplicationCallDto
{
    [IgnoreDataMember]
    private Exception exception;
    [DataMember]
    private string exceptionString;
    [DataMember]
    private string sessionId = null;
    [DataMember]
    private MyType myType = null;
}

当我以Exception类型将IgnoreDataMember添加到字段时,我可以毫无问题地为客户端生成代码。但是如果加上DataMember,什么也不会产生。

为什么?如何将Exception类型添加到DataContract类型中?

DataContract which includes Exception

这不是一个真正的答案,只是一些关于异常序列化的注释,我想为一些代码提供额外的空间…

你想过用FaultContracts来代替吗?http://msdn.microsoft.com/en-us/library/ms733721.aspx

虽然Exception类型是可序列化的,但通常_data字段中设置的内容都是不可序列化的,并且有时会导致序列化问题。在这里看到的。解决这个问题的方法是在序列化之前将_data字段设置为null:

        Exception ex = error;
        FieldInfo fieldInfo = typeof(Exception).GetField("_data", BindingFlags.Instance | BindingFlags.NonPublic);
        while (ex != null)
        {
            fieldInfo.SetValue(ex, null);
            ex = ex.InnerException;
        }

另一个问题是,通过向DataContract添加Exception类型,您只覆盖了实际Exception实例的情况:

AbstractApplicationCallDto.Exception = new Exception();
然而,任何Exception的派生都不能工作,例如:
AbstractApplicationCallDto.Exception = new NullReferenceException();

要做到这一点,你必须在你的数据契约中添加一个[KnownType]属性,所以你最终会得到这样的东西:

[DataContract]
[KnownType(typeof(NullReferenceException))]
[KnownType(typeof(InvalidOperationException))]
[KnownType(typeof(ApplicationException))]
[KnownType(typeof(...))] // add one for every type of exception you might need to serialize back, or that might be contained in Exception.InnerException
public partial class AbstractApplicationCallDto
{
    ...

回到你最初的问题,我想不出为什么客户端生成工具在合同中有Exception类型时无法生成任何东西…它给出一个错误吗?它生成任何代码吗?

我也有这个问题;我能够通过使字段类型为ExceptionDetail并使用它来包装Exception对象来绕过它。例子:

[DataContract]
public class WebServiceFault
{
    public WebServiceFault(Exception ex)
    {
        Message = ex.Message;
        InnerException = new ExceptionDetail(ex);
    }
    [DataMember]
    public string Message
    {
        get;
        private set;
    }
    [DataMember]
    public ExceptionDetail InnerException
    {
        get;
        private set;
    }
}