2010-07-20 21 views
6

मेरे पास XML से ऑब्जेक्ट्स को क्रमबद्ध करने और deserializing के लिए एक मौजूदा कक्षा है। यह एक सामान्य वर्ग है जिसमें एकल प्रकार पैरामीटर T है जिसका एकमात्र बाधा where T : IXmlSerializable है। हालांकि, मैं अभी भी कक्षाओं पर इस कक्षा का उपयोग करने में सक्षम होना चाहता हूं जो IXmlSerializable लागू नहीं करता है लेकिन [Serializable] विशेषता है। मैं यह करने के बारे में कैसे जा सकता हूं?सी # जेनेरिक सीरियलाइजेशन यूटिलिटी क्लास

मेरी सामान्य वर्ग से:

public static class XmlSerializationUtils<T> where T : IXmlSerializable 
{ 
    public static T DeserializeXml(XmlDocument xml) { ... } 
    public static XmlDocument SerializeToXml(T toSerialize) { ... } 
} 

मैं this discussion पाया लेकिन कोई समाधान दिया था, सिर्फ इतना है कि मैं where T : Serializable नहीं कर सकते। where T : SerializableAttribute करने का प्रयास करने से विजुअल स्टूडियो का कहना है कि "सीलबंद क्लास 'सिस्टम का उपयोग नहीं कर सकता। SerializableAttribute' टाइप पैरामीटर बाधा के रूप में"।

संपादित करें: पर Stephen's answer आधारित, मैं XmlSerializationUtils<T> पर बाधाओं को हटा दिया है और इस स्थिर निर्माता कहा:

static XmlSerializationUtils() 
{ 
    Type type = typeof(T); 
    bool hasAttribute = null != Attribute.GetCustomAttribute(type, 
     typeof(SerializableAttribute)); 
    bool implementsInterface = 
     null != type.GetInterface(typeof(IXmlSerializable).FullName); 
    if (!hasAttribute && !implementsInterface) 
    { 
     throw new ArgumentException(
      "Cannot use XmlSerializationUtils on class " + type.Name + 
      " because it does not have the Serializable attribute " + 
      " and it does not implement IXmlSerializable" 
     ); 
    } 
} 

उत्तर

6

आप जेनरिक के हिस्से के रूप में एक विशेषता की आवश्यकता नहीं कर सकते हैं। हालांकि, आप एक स्थिर कन्स्ट्रक्टर प्रदान कर सकते हैं जो इसके लिए जांच करता है और अगर यह नहीं मिलता है तो फेंकता है।

5

मैं सिर्फ प्रकार बाधा को खत्म करने और SerializationException पकड़ने जब प्रकार क्रमानुसार नहीं करता है या ठीक से deserialize ... वास्तव में, यह अपने सामान्य क्रमानुसार की अनुमति देता है और तरीकों deserialize एक फ़ॉर्मेटर

public enum Formatter { Binary, Xml } 

स्वीकार करने के लिए चाहते हैं कि को नियंत्रित कर सकता है क्रमबद्धता है कि क्या द्विआधारी या एक्सएमएल

public class Serialization 
{ 
    public enum Formatter { Binary, Xml } 

    #region Serialization methods 
    public static void Serialize2File<T>(T obj, string pathSpec, 
     Formatter formatter) 
    { 
     try 
     { 
      switch (formatter) 
      { 
       case (Formatter.Binary): 
        using (var fs = new FileStream(pathSpec, FileMode.Create, 
             FileAccess.Write, FileShare.Write)) 
         (new BinaryFormatter()).Serialize(fs, obj); 
        break; 

       case (Formatter.Xml): 
        var serializer = new XmlSerializer(typeof(T)); 
        TextWriter textWriter = new StreamWriter(pathSpec); 
        serializer.Serialize(textWriter, obj); 
        textWriter.Close(); 
        break; 

       default: 
        throw new MyCustomException("Invalid Formatter option"); 
      } 
     } 
     catch (SerializationException sX) 
     { 
      var errMsg = String.Format(
       "Unable to serialize {0} into file {1}", 
       obj, pathSpec); 
      throw new MyCustomException(errMsg, sX); 
     } 
    } 
    public static T DeSerializeFromFile<T>(string pathSpec, 
     Formatter formatter) where T : class 
    { 
     try 
     { 
      switch (formatter) 
      { 
       case (Formatter.Binary): 
        using (var strm = new FileStream(pathSpec, 
             FileMode.Open, FileAccess.Read)) 
        { 
         IFormatter fmt = new BinaryFormatter(); 
         var o = fmt.Deserialize(strm); 
         if (!(o is T)) 
          throw new ArgumentException("Bad Data File"); 
         return o as T; 
        } 

       case (Formatter.Xml): 
        var serializer = new XmlSerializer(typeof(T)); 
        TextReader rdr = new StreamReader(pathSpec); 
        return (T)serializer.Deserialize(rdr); 

       default: 
        throw new MyCustomException("Invalid Formatter option"); 
      } 
     } 
     catch (SerializationException sX) 
     { 
      var errMsg = String.Format(
       "Unable to deserialize {0} from file {1}", 
       typeof(T), pathSpec); 
      throw new MyCustomException(errMsg, sX); 
     } 
    } 
    #endregion Serialization methods 
} 
+0

यह एक अनुचित समाधान नहीं है। –

+0

हाँ, मैं सहमत हूं, इसका उपयोग ऐसे डेवलपर द्वारा किया जा रहा है, जो जानता है कि वह वर्ग जो धारावाहिक करने की कोशिश कर रहा है वह सरलीकृत है, अगर वह गलत इस्तेमाल करता है तो यह अपवाद है कि आप संकलन समय पर हर सकारात्मक बग को खत्म नहीं कर सकते हैं। –

+0

@ बेन: हम हमेशा ऐसा नहीं कर सकते हैं, लेकिन हमें निश्चित रूप से जल्दी और अक्सर बग पकड़ने की कोशिश करनी चाहिए। इस मामले में, हम इसे संकलित समय पर नहीं पकड़ सकते हैं, लेकिन अगर हम स्थिर कन्स्ट्रक्टर चाल का उपयोग करते हैं, तो हम इसे रन टाइम की शुरुआत में पकड़ सकते हैं (जिसका मतलब है कि एक पोस्ट-कंपाइल धुआं चेक इसे याद नहीं करेगा)। –

8

आप अगर एक प्रकार वस्तु के प्रकार के IsSerializable संपत्ति का उपयोग कर serializable है देखने के लिए जाँच कर सकते हैं।

myObj.GetType().IsSerializable 

जैसा कि बताया गया है, सामान्य बाधा के रूप में जोड़ना संभव नहीं है, लेकिन संभवतः एक निर्माता में चेक किया जाएगा।

+0

यह विशेषता की जांच करने से बेहतर है। धन्यवाद। –

+0

एचएम। मेरा वर्तमान समाधान (मेरे प्रश्न में) यह देखने के लिए जांच करता है कि क्या 'IXmlSerializable' या' [Serializable] 'दिए गए वर्ग' T' पर लागू होता है। क्या दोनों के लिए 'IsSerializable' खाता है? स्पष्ट रूप से –

+0

। Http://msdn.microsoft.com/en-us/library/system.type.isserializable.aspx देखें –

संबंधित मुद्दे