2010-08-31 18 views
8

जबकि मुझे एहसास है कि एक समान प्रश्न है (How to serialize an Exception object in C#?), और हालांकि उस पृष्ठ के उत्तर सहायक थे, लेकिन उन्होंने समस्या को हल नहीं किया या प्रश्न का उत्तर नहीं दिया।अपरिवर्तनीय अपवाद को फेंकने योग्य

मेरा मानना ​​है कि सवाल यह था कि ऑब्जेक्ट को क्रमबद्ध करने के लिए यह उसी वस्तु में पुनर्निर्मित (deserialized) की अनुमति देने के लिए था। मैंने davogones और Antony Booth द्वारा दिए गए समाधान का उपयोग करने का प्रयास किया है, लेकिन उपभोग करने वाले पक्ष (SerializationException: Exception) में System.Exception बेस क्लास को जोड़ने के बिना, इन प्रकारों (स्वयं द्वारा) वास्तविक अपवाद वस्तुओं के रूप में उपयोग करना असंभव है फेंक दिया।

जारी रखने से पहले, मुझे अंतिम बयान समझाएं। मैंने एक वेब सेवा में Antony Booth's solution का उपयोग करने की कोशिश की है (सेवा में सीरियलज़ेबल ऑब्जेक्ट की परिभाषा है) सभी उपभोक्ताओं को एक ही अपवाद का उपयोग करने के प्रयास में (उम्मीद है कि इसे पुन: उपयोग करने के बजाय एक पुन: प्रयोज्य धारावाहिक अपवाद प्रकार बनाना)।

दुर्भाग्यवश, चूंकि इनमें से कोई भी प्रकार स्पष्ट रूप से System.Exception से प्राप्त नहीं हुआ है, इसलिए आप throw नहीं कर सकते हैं, जो स्पष्ट रूप से उपयोगी होगा। जैसा कि मैंने उपर्युक्त उल्लेख किया है, ऐसा लगता है कि उपभोग करने वाली तरफ टाइप श्रेणी परिभाषा के लिए : Exception जोड़ना वस्तु को फेंकने की अनुमति देता है, लेकिन इसके लिए स्वत: जेनरेट किए गए डब्लूएसडीएल/वेब सेवा कोड को संपादित करने की आवश्यकता होती है, जो सहज रूप से खराब/गैर-रखरखाव की तरह लगती है मेरे लिए अभ्यास करें (अगर मैं गलत हूं तो मुझे सही करें)।

मेरा पहला सवाल है, फिर से, System.Exception को क्रमबद्ध करना संभव है या व्युत्पन्न प्रकार बनाने के लिए संभव है, और यदि यह संभव है, तो ऐसा करने के बारे में कोई कैसे होगा? मुझे जिक्र करना चाहिए कि मैंने देखा है कि reconstitute the Exception object का आधिकारिक तरीका क्या है, लेकिन मुझे डर है कि मैं इसे बहुत अच्छी तरह समझ नहीं पा रहा हूं।

मेरा दूसरा प्रश्न System.Exception की वास्तुकला के बारे में है। मैं क्या जानना चाहता हूं कि System.Exception प्रकार को [Serializable] के रूप में चिह्नित किया गया है, जब इसे दस्तावेज किया गया है और स्पष्ट रूप से इसे सही ढंग से क्रमबद्ध करने से आपको अस्वीकार करने के लिए डिज़ाइन किया गया है (कम से कम एक्सएमएल के साथ) क्योंकि यह Data ऑब्जेक्ट IDictionary लागू करता है?

से MSDN:

प्रश्न: मैं hashtables क्यों क्रमानुसार नहीं कर सकते?

ए: XmlSerializer IDictionary इंटरफ़ेस को लागू करने वाले वर्गों को संसाधित नहीं कर सकता है। यह आंशिक रूप से अनुसूची बाधाओं के कारण था और आंशिक रूप से इस तथ्य के कारण कि हैशटेबल में एक्सएसडी प्रकार प्रणाली में समकक्ष नहीं है। एकमात्र समाधान कस्टम हैशटेबल को कार्यान्वित करना है जो IDictionary इंटरफ़ेस को लागू नहीं करता है।

यह देखते हुए कि एक्सएमएल होता जा रहा है (यदि नहीं पहले से ही है) डेटा परिवहन (आधिकारिक तौर पर माइक्रोसॉफ्ट, फिर भी द्वारा अनुशंसित) के लिए एक नया मानक, यह मूर्खता मूर्ख लगता है .NET में केवल ऑब्जेक्ट प्रकार है कि हो सकता है की अनुमति नहीं करने के लिए XML-serializable नहीं होने के लिए फेंक दिया।

मैं सभी सोर्स से कुछ विचार सुनने की उम्मीद करता हूं (खासकर जब यह मेरी पहली पोस्ट है)।

यदि आपके पास प्रश्न हैं या स्पष्टीकरण की आवश्यकता है, तो कृपया मुझे बताने में संकोच न करें।


नोट: मैं सिर्फ this SO post पाया है, जो कुछ सवालों के जवाब देने लगता है, लेकिन मुझे लगता है मैं उस पर अपने ही अजीब उठाना चाहते हैं। अगर मुझे डुप्लिकेट के बहुत करीब है, तो मुझे बताएं।

उत्तर

1

आप Exception से प्राप्त कक्षा बना सकते हैं और ISerializable इंटरफ़ेस को कार्यान्वित करके स्वयं क्रमबद्धता और deserialization कर सकते हैं।

उदाहरण wrox forums से लिया, 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 
    } 
} 
+1

बस एक त्वरित नोट कि 'एप्लिकेशन अपवाद' को बहिष्कृत कर दिया गया है और _not_ का उपयोग या उपclassed नहीं होना चाहिए। इसके बजाए 'अपवाद' का प्रयोग करें। – thecoop

+0

दुर्भाग्यवश, यह वेब सेवाओं के संदर्भ में काम नहीं कर रहा है। मैंने आपके कोड की प्रतिलिपि बनाई और 'ApplicationException' को 'अपवाद' में बदल दिया, और मुझे वही त्रुटि कोड मिला जो मैं पहले संदर्भित कर रहा था: सदस्य सिस्टम को क्रमबद्ध नहीं कर सकता। अपवाद। प्रकार का डेटा System.Collections.IDictionary, क्योंकि यह उपकरण IDictionary। बस '[सीरियलज़ेबल]' जोड़ना पर्याप्त नहीं है। – llaughlin

+0

एचआरएम। हो सकता है कि आप _data सदस्य को एक धारावाहिक संग्रह में बदल सकें जो IDictionary को लागू नहीं करता है? वहां कुछ कार्यान्वयन हैं जो ऐसा करते हैं। –

0

दो कक्षाएं होने पर विचार करें।

पहला धारावाहिक अपवाद डिस्क्रिप्शन क्लास होगा, जो उन गुणों को लागू करना होगा जिन्हें आप क्रमबद्ध करना चाहते हैं, और कुछ भी नहीं प्राप्त करते हैं। दूसरा कस्टम अपवाद है जो अपवाद से प्राप्त होगा, और अपवाद डिस्क्रिप्शन के उदाहरण के लिए एक संदर्भ है। साथ ही, कस्टमएक्सप्शन "सार्वजनिक स्थिर अंतर्निहित ऑपरेटर" लागू करेगा ताकि आप स्वाभाविक रूप से दो कार्यान्वयन के बीच आगे बढ़ सकें।

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 
संबंधित मुद्दे