序列化异常是可抛出的

lla*_*lin 8 .net c# serialization exception

虽然我意识到有一个类似的问题(如何在C#中序列化异常对象?),虽然该页面上的答案很有帮助,但它们并没有完全解决问题或回答提出的问题.

我相信问题是如何序列化对象以允许它被重建(反序列化)到同一个对象中.我试图使用davogonesAntony Booth给出的解决方案,但是没有System.Exception在消费方面添加基类(如:),SerializationException: Exception不可能将这些类型(通过它们自己)用作可以抛出的实际异常对象.

在我继续之前,让我解释一下最后的陈述.我试图在Web服务中使用Antony Booth的解决方案(该服务包含可序列化对象的定义),试图让所有消费者使用相同的异常(希望创建一个可重用的可序列化异常类型,而不是重新创建它) .

不幸的是,由于两种类型都没有明确地衍生出来System.Exception,你不能使用throw它们,这显然是有用的.就像我上面提到的那样,似乎: Exception在消费方面添加类型类定义允许抛出对象,但这需要编辑自动生成的WSDL/Web服务代码,这看起来像是一个糟糕/不可维护的实践对我(如果我错了,请纠正我).

我的第一个问题是,是否可以序列化System.Exception或创建可以序列化的派生类型,如果可能的话,怎么会这样做呢?我应该提一下,我已经看过了重建这个Exception对象的正式方法,但我恐怕不太了解它.

我的第二个问题是关于System.Exception自身的架构.我想知道的是为什么System.Exception类型被标记为何[Serializable]时被记录并且显然被设计为禁止您正确地序列化它(至少使用XML),因为它的Data对象是实现的IDictionary

来自MSDN:

问:为什么我不能序列化哈希表?

答:XmlSerializer无法处理实现IDictionary接口的类.这部分是由于计划约束,部分原因是哈希表在XSD类型系统中没有对应物.唯一的解决方案是实现一个不实现IDictionary接口的自定义哈希表.

鉴于XML正在成为(如果不是已经是)数据传输的新标准(尽管如此,微软正式推荐),不允许.NET中唯一可以抛出的对象类型不是XML可序列化的,这似乎是非常愚蠢的. .

我期待听到所有SO'rs的一些想法(特别是因为这是我的第一篇文章).

如果您有疑问或需要澄清,请随时告诉我.


注意:我刚刚发现了这个SO帖子,它似乎回答了几个问题,但我想我想对此进行自己的打击.但是,让我知道它是否太接近重复.

axe*_*l_c 2

您可以创建一个派生类,并通过实现ISerializedException接口自行进行序列化和反序列化。

示例取自wrox 论坛,子类化ApplicationException

编辑:正如所指出的,ApplicationException已被弃用。使用基Exception类应该可以正常工作。

using System;
using System.Collections;
using System.Runtime.Serialization;

namespace Common.CustomExceptions
{

    /// <summary>
    /// Custom exception.
    /// </summary>
    [Serializable]
    public class CustomExceptionBase: ApplicationException
        {

        // Local private members
        protected DateTime _dateTime = DateTime.Now;
        protected String _machineName = Environment.MachineName;
        protected String _exceptionType = "";
        private String _exceptionDescription = "";
        protected String _stackTrace = "";
        protected String _assemblyName = "";
        protected String _messageName = "";
        protected String _messageId = "";
        protected Hashtable _data = null;
        protected String _source = "";
        protected Int32 _exceptionNumber = 0;

        public CustomExceptionBase(): base()
        {
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }

        public CustomExceptionBase(Int32 exceptionNumber): base()
        {
            this._exceptionNumber = exceptionNumber;
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }

        public CustomExceptionBase(Int32 exceptionNumber, String message): base(message)
        {
            this._exceptionNumber = exceptionNumber;
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }

        public CustomExceptionBase(Int32 exceptionNumber, String message, Exception innerException): 
            base(message, innerException)
        {
            this._exceptionNumber = exceptionNumber;
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }

        public CustomExceptionBase(Int32 exceptionNumber, String message, Exception innerException, String messageName, String mqMessageId): 
            base(message, innerException)
        {
            this._exceptionNumber = exceptionNumber;
            this._messageId = mqMessageId;
            this._messageName = messageName;
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }

        public CustomExceptionBase(Int32 exceptionNumber, String message, Exception innerException, String messageName, String mqMessageId, String source): 
            base(message, innerException)
        {
            this._exceptionNumber = exceptionNumber;
            this._messageId = mqMessageId;
            this._messageName = messageName;
            this._source = source.Equals("") ? this._source : source;
            if (Environment.StackTrace != null)
                this._stackTrace = Environment.StackTrace;
        }


        #region ISerializable members

        /// <summary>
        /// This CTor allows exceptions to be marhalled accross remoting boundaries
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        protected CustomExceptionBase(SerializationInfo info, StreamingContext context) :
            base(info,context)
        {
            this._dateTime = info.GetDateTime("_dateTime");
            this._machineName = info.GetString("_machineName");
            this._stackTrace = info.GetString("_stackTrace");
            this._exceptionType = info.GetString("_exceptionType");
            this._assemblyName = info.GetString("_assemblyName");
            this._messageName = info.GetString("_messageName");
            this._messageId = info.GetString("_messageId");
            this._exceptionDescription = info.GetString("_exceptionDescription");
            this._data = (Hashtable)info.GetValue("_data", Type.GetType("System.Collections.Hashtable"));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("_dateTime", this._dateTime);
            info.AddValue("_machineName", this._machineName);
            info.AddValue("_stackTrace", this._stackTrace);
            info.AddValue("_exceptionType", this._exceptionType);
            info.AddValue("_assemblyName", this._assemblyName);
            info.AddValue("_messageName", this._messageName);
            info.AddValue("_messageId", this._messageId);
            info.AddValue("_exceptionDescription", this._exceptionDescription);
            info.AddValue("_data", this._data, Type.GetType("System.Collections.Hashtable"));
            base.GetObjectData (info, context);
        }

        #endregion
    }
}
Run Code Online (Sandbox Code Playgroud)