5

Burada basitlik amacıyla, örnek kodumu meyve kullanarak göstereceğim. Aslında, daha anlamlı bir şey yapıyorum (umarız).Geçersiz bir enum öğesini serileştirme istisnasını nasıl önlersiniz?

public enum FruitType 
{ 
    Apple, 
    Orange, 
    Banana 
} 

Ve bir sınıf:

[Serializable] 
public class Fruit 
{ 
    public FruitType FruitType { get; set; } 
    public Fruit(FruitType type) 
    { 
     this.FruitType = type; 
    } 
} 

Biz serialize ve de-serialize biz bir enum var diyelim. Şimdi, şimdi olduğu, böylece enum revize sağlar: Ne zaman önce tefrika nesneleri de-serializing

public enum FruitType 
{ 
    GreenApple, 
    RedApple, 
    Orange, 
    Banana 
} 

, sen Apple (orijinal enum öğesi) gibi System.InvalidOperation istisna olsun geçerli değil. Nesne, serileştirilmiyor.

[XmlElement(ElementName = "Mode")] 
    public FruitType FruitType { get; set; } 

Şimdi de-serileştirme sırasında eski mülkiyet dikkate alınmaz alır şöyledir: Bunu çözmek başardı

bir yolu tefrika aldığında Fruit sınıfında farklı bir ad FruitType özelliği vermekti bulunamadığı gibi. Seri dışı bırakma sırasında geçersiz enum öğelerini yok saymanın/atlamanın bir yolu olup olmadığını bilmek istiyorum, böylece hiçbir özel durum atılmıyor ve nesne yine de serileştirilmiyor.

+1

Ben çalışan bir örnek proje dahil bağlantılı soruya cevabım bakın olmak istediğiniz yere size yol en iyi şekilde olmalıdır: http://stackoverflow.com/a/10709040 – user423430

cevap

3

Apple'u bırakın ve ObsoleteAttribute ile işaretleyin. Bu şekilde, Apple kullanarak herhangi bir kod bir derleyici uyarısı üretecektir.

+0

'Apple' enum öğesinin üstüne [Eski] ekledim. Ancak, seri hale getirme ve eski nesne kullanıldığında şu istisnaları hala yaşıyorum: Örnek doğrulama hatası: 'Apple', FruitType için geçerli bir değer değil. – Elan

0

Bir similar question gönderdim ve XML dosyasında Apple ile iletişim kurarken atılan istisnayı yakalamak için basit bir yöntem bulamadım. Özniteliklerin veya öğelerin eksik olması için deserialiation sırasında birtakım diğer istisnaları yakalayabilirim, ancak geçersiz bir enum değeri için değil. Geçersiz enum değeri (sizin durumunuzda Apple) beni seriden arındırıyor.

Olası bir çözüm, Meyve sınıfında IXMLSerializable uygulamaktır. Desterizer tarafından IXMLSerailizable.ReadXML() yöntemi çağrıldığında, size nelerin geçtiğini görmeniz gerekir. Değer "Apple" olduğunda, enum'u bazı mantıklara göre GreenApple veya RedApple olarak ayarlayın.

0

Benzer yanıtları kendim aradım ve XML, geçerli olmayan bir enum için bir değer içeriyorsa bu özel durumu yakalamak için yazdım. Bu elemanı çıkarır ve tekrar seri hale getirmeye çalışır. Eğer eleman gerekli ise, hala bir istisna alacaksınız. Bu kusurlu, ama

private const string XmlError = "There is an error in XML document "; 
    private const string InstanceValidationError = "Instance validation error:"; 
    private static readonly Regex XmlErrorRegex = new Regex("There is an error in XML document \\((\\d+), (\\d+)\\)."); 
    private static readonly Regex InstanceValidationErrorRegex = new Regex("Instance validation error: '(\\S+)' is not a valid value for (\\S+)."); 
    private const string TagFinderString = "\\>{0}\\</(\\S+)\\>"; 

    /// <summary> 
    /// Helper method to deserialize xml message 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="message"></param> 
    /// <returns></returns> 
    public T Deserialize(string message) 
    { 
     var result = default(T); 
     if (!string.IsNullOrEmpty(message)) 
     { 
      using (var reader = new StringReader(message)) 
      { 
       try 
       { 
        result = (T)_serializer.Deserialize(reader); 
       } 
       catch (InvalidOperationException ex) 
       { 
        if (ex.Message.StartsWith(XmlError)) 
        { 
         if(ex.InnerException != null && ex.InnerException.Message.StartsWith(InstanceValidationError)) 
         { 
          var instanceValidationErrorMatches = InstanceValidationErrorRegex.Matches(ex.InnerException.Message); 
          if (instanceValidationErrorMatches.Count > 0) 
          { 
           var locationMatches = XmlErrorRegex.Matches(ex.Message); 
           var startIndex = GetStartIndex(message, locationMatches); 
           var match = instanceValidationErrorMatches[0]; 
           if(match.Groups.Count > 0) 
           { 
            var toRemove = GetToRemove(message, match, startIndex); 

            return Deserialize(message.Replace(toRemove, string.Empty)); 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
     return result; 
    } 

    private static string GetToRemove(string message, Match match, int startIndex) 
    { 
     var value = match.Groups[1]; 
     var tagFinder = new Regex(string.Format(TagFinderString, value)); 
     var tagFinderMatches = tagFinder.Matches(message.Substring(startIndex)); 
     var tag = tagFinderMatches[0].Groups[1]; 

     return string.Format("<{0}>{1}</{0}>", tag, value); 
    } 

    private static int GetStartIndex(string message, MatchCollection locationMatches) 
    { 
     var startIndex = 0; 
     if (locationMatches.Count > 0) 
     { 
      var lineNumber = int.Parse(locationMatches[0].Groups[1].Value); 
      var charIndex = int.Parse(locationMatches[0].Groups[2].Value); 
      using (var locationFinder = new StringReader(message)) 
      { 
       for (var i = 1; i < lineNumber; i++) 
       { 
        startIndex += locationFinder.ReadLine().Length; 
       } 
      } 
      startIndex += charIndex; 
     } 
     return startIndex; 
    } 
İlgili konular