Сериализация исключения для throwable
хотя я понимаю, что есть подобный вопрос (как сериализовать объект исключения в C#?), и хотя ответы на этой странице были полезны, они не совсем решили проблему или ответили на поставленный вопрос.
я считаю, что вопрос состоял в том, как сериализовать объект, чтобы позволить ему быть реконструированным (десериализованным) в тот же объект. Я попытался использовать решение, данное davogones и Энтони Бут, но без добавления System.Exception
базовый класс, на стороне потребления (как в: SerializationException: Exception
), невозможно использовать эти типы (сами по себе) в качестве фактических объектов исключения, которые могут быть брошены.
прежде чем я продолжу, позвольте мне объяснить, что последнее заявление. Я пытался использовать решение Антония Бута в веб-службе (служба содержит определение для сериализуемого объекта) в попытке заставить всех потребителей использовать одно и то же исключение (надеюсь, создание многоразового сериализуемый тип исключения вместо того, чтобы воссоздавать его повсюду).
к сожалению, поскольку ни один из типов явно не является производным от System.Exception
нельзя throw
их, что, очевидно, было бы полезно. Как я уже упоминал выше, кажется, что добавление : Exception
к определению класса типа на стороне потребления позволяет объекту быть брошенным, но это требует редактирования автоматически сгенерированного кода WSDL / веб-службы, который интуитивно кажется мне плохой / не поддерживаемой практикой (правильно я, если я ошибаюсь).
мой первый вопрос, опять же, можно ли сериализовать мой второй вопрос касается архитектуры . Что я хотел бы знать, почему the С MSDN: Q: почему я не могу сериализовать хэш-таблицы? A: XmlSerializer не может обрабатывать классы, реализующие интерфейс IDictionary. Отчасти это было связано с графиком ограничения и частично из-за того, что хэш-таблица не имеет аналога в системе типа XSD. Единственное решение-реализовать пользовательскую хэш-таблицу, которая не реализует интерфейс IDictionary. учитывая, что XML становится (если еще не является) новым стандартом для транспортировки данных (официально рекомендованным Microsoft, тем не менее), кажется абсурдно глупым не разрешать единственный тип объекта в .NET, который может быть брошен, чтобы не быть В XML-сериализацию. я с нетерпением жду услышать некоторые мысли от всех SO'RS (тем более, что это мой первый пост). если у вас есть вопросы или нужны разъяснения, пожалуйста, не стесняйтесь дайте мне знать. примечание: Я только что нашел это так пост, что, кажется, отвечает на несколько вопросов, но я думаю, что я хотел бы получить свой собственный удар. дайте мне знать, если это слишком близко к дубликату. System.Exception
или создать производный тип, который может быть сериализован, и если это возможно,как это сделать? Я должен упомянуть, что я посмотрел на то, что кажется официальным способом восстановить Exception
объект
System.Exception
тип помечен как [Serializable]
когда он был задокументирован и, по-видимому, разработан, чтобы запретить вам сериализацию его должным образом (по крайней мере, с XML), потому что это Data
объект IDictionary
?
2 ответов
можно создать класс, производный от Exception
и выполните сериализацию и десериализацию самостоятельно, реализовав ISerializable интерфейс.
пример взят из издательства 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
}
}
рассмотреть два класса.
первым будет сериализуемый класс ExceptionDescription, который должен реализовать атрибуты, которые вы хотите сериализовать, и наследуется от nothing. Второй-CustomException, который наследуется от Exception и имеет одну ссылку на экземпляр ExceptionDescription. Кроме того, CustomException реализует "открытый статический неявный оператор", поэтому вы можете естественным образом перемещаться между двумя реализациями.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Xml.Serialization;
namespace SerializableException {
public class CustomException : Exception {
public CustomException(ExceptionDescription d) {
this.description = d;
}//method
public CustomException(String message, Exception e) {
this.description = new ExceptionDescription(message, e, 2);
}//method
public CustomException(String message, Exception e, int stackDepth) {
this.description = new ExceptionDescription(message, e, stackDepth + 1);
}//method
public CustomException(String message, IEnumerable<Exception> causes) {
this.description = new ExceptionDescription(message, causes, 2);
}//method
public CustomException(String message, IEnumerable<Exception> causes, int stackDepth) {
this.description = new ExceptionDescription(message, causes, stackDepth + 1);
}//method
public CustomException(String message) {
this.description = new ExceptionDescription(message, 2);
}//method
public CustomException(String message, int stackDepth) {
this.description = new ExceptionDescription(message, stackDepth + 1);
}//method
public CustomException() {
}//method
public static CustomException newInstance(Exception e) {
if (e == null) return null;
if (e is CustomException) return (CustomException)e;
CustomException output = new CustomException();
output.description = ExceptionDescription.newInstance(e);
return output;
}//method
public static implicit operator ExceptionDescription(CustomException e) {
if (e == null) return null;
return e.description;
}//method
public static implicit operator CustomException(ExceptionDescription d) {
return d == null ? null : new CustomException(d);
}//method
public ExceptionDescription description;
public String RawStackTrace {
get { return description.RawStackTrace; }
//set { rawStackTrace = value; }
}//method
public DateTime Time {
get { return description.Time; }
}//method
public override String Message {
get { return description.Message; }
}//method
}//class
[XmlRoot]
public class ExceptionDescription {
public ExceptionDescription() {
}//method
public ExceptionDescription(String message, Exception cause, int stackDepth) {
this.Message = message;
this.Time = DateTime.Now;
this.RawStackTrace = new StackTrace(1 + stackDepth, true).ToString();
this.Causes = new ExceptionDescription[] { ExceptionDescription.newInstance(cause) };
}//method
public ExceptionDescription(String message, IEnumerable<Exception> causes, int stackDepth) {
this.Message = message;
this.Time = DateTime.Now;
this.RawStackTrace = new StackTrace(1 + stackDepth, true).ToString();
this.Causes = (from Exception e in causes select ExceptionDescription.newInstance(e)).ToArray();
}//method
public ExceptionDescription(String message, int stackDepth) {
this.Message = message;
this.Time = DateTime.Now;
this.RawStackTrace = new StackTrace(stackDepth + 1, true).ToString();
this.Causes = new ExceptionDescription[0];
}//method
public static ExceptionDescription newInstance(Exception e) {
if (e == null) return null;
if (e is CustomException) return ((CustomException)e).description;
ExceptionDescription output = new ExceptionDescription();
output.Time = DateTime.Now;
output.Message = e.Message;
output.RawStackTrace = e.StackTrace;
if (e.InnerException != null) {
output.Causes = new ExceptionDescription[] { ExceptionDescription.newInstance(e.InnerException) };
} else {
output.Causes = new ExceptionDescription[0];
}//endif
return output;
}//method
public String Message;
public ExceptionDescription[] Causes; //MORE THAN ONE CAUSE IS LEGITIMATE
public String RawStackTrace;
public DateTime Time;
}//class
}//namespace