2010-07-20 12 views
6

XML'e/nesnesinden nesneleri serileştirmek ve serileştirmek için var olan bir sınıfa sahibim. Tek kısıtlama T olan ve tek kısıtlaması where T : IXmlSerializable olan genel bir sınıftır. Ancak, hala bu sınıfı IXmlSerializable'u uygulamayan ancak [Serializable] özniteliğine sahip sınıflarda kullanmak istiyorum. Bunu yapmayı nasıl başarabilirim? Benim genel sınıfındanC# genel seri hale getirme yardımcı programı sınıfı

:

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

Ben this discussion buldum ama verilen hiçbir çözüm ben where T : Serializable yapamaz sadece vardı. where T : SerializableAttribute yapmayı denediğinde, Visual Studio'nun "Serial sınıf" System.SerializableAttribute 'tür parametre kısıtlaması olarak kullanılamıyor "olduğunu söylüyor.

Düzenleme:Stephen's answer dayalı, ben XmlSerializationUtils<T> üzerinde kısıtlamalar kaldırılmış ve bu statik yapıcı ekledi: Sen jenerik bir parçası olarak bir özelliğin gerekli edemez

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" 
     ); 
    } 
} 

cevap

6

. Bununla birlikte, onu kontrol eden ve bulunmazsa atar statik bir kurucu sağlayabilirsiniz.

5

Sadece tip kısıtlamasını ortadan kaldırmak ve tip seri veya düzgün serisini vermediğinde SerializationException yakalamak ... Aslında bu da jenerik serialize izin verir ve bir biçimlendirici

public enum Formatter { Binary, Xml } 

kabul etmek yöntemlerini Deserialize ediyorum bu seri hale olup olmadığını kontrol edebilecek ikili veya 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

Bu mantıksız bir çözüm değil. –

+0

Evet, katılıyorum sınıfının serileştirmeye çalışıp çalışmadığını öğrenmek isteyen bir geliştirici tarafından kullanılıyor, eğer istisnaların ne olduğu yanlışsa, derleme zamanında her olası hatayı ortadan kaldıramazsınız. –

+0

@Ben: Her zaman bunu yapamayız, ancak hataları erken ve sık sık yakalamaya çalışmalıyız. Bu durumda, derleme zamanında yakalayamayız, ancak statik kurucu hilesi kullanırsak, onu çalışma zamanının en başında yakalayabiliriz (bu, derleme sonrası bir duman kontrolü bunu kaçırmaz). –

8

bir tür nesnenin türü IsSerializable özelliğini kullanarak seri hale olup olmadığını görmek için kontrol edebilirsiniz. Belirtildiği gibi

myObj.GetType().IsSerializable 

, bu genel bir kısıtlama olarak eklemek mümkün değildir, ancak büyük olasılıkla bir yapıcı kontrol edilecektir.

+0

Bu özellik için kontrol etmek daha iyidir. Teşekkürler. –

+0

Hm. Benim şu anki çözümüm (sorularımda), "IXmlSerializable" veya "[Serializable]" öğelerinin, "T" sınıfı için geçerli olup olmadığını kontrol eder. Her ikisi için de "IsSerializable" hesabı var mı? –

+0

Görünüşe göre. Http://msdn.microsoft.com/en-us/library/system.type.isserializable.aspx adresine bakın. –

İlgili konular