5

간단히하기 위해 과일을 사용하여 샘플 코드를 보여 드리겠습니다. 실제로 저는 좀 더 의미있는 일을하고 있습니다.잘못된 enum 항목을 deserialize하는 예외를 방지하는 방법은 무엇입니까?

public enum FruitType 
{ 
    Apple, 
    Orange, 
    Banana 
} 

그리고 클래스 :

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

우리는 직렬화를 해제 직렬화 할 수 있습니다 우리가 열거 있다고 가정 해 봅시다. 자, 지금 있도록 열거을 개정 할 수 있습니다 : 때 이전에 직렬화 된 객체를 해제 직렬화

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

, 당신이 Apple (원래 열거 항목)으로 System.InvalidOperation 예외가 유효하지 않습니다. 객체는 비 직렬화되지 않습니다.

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

자, 드 - 직렬화시에 기존의 특성이 무시됩니다 다음과 같이 나는이 문제를 해결 할 수 있었다

한 가지 방법은 직렬화됩니다 때 Fruit 클래스에 다른 이름을 FruitType 속성을 제공하는 것이 었습니다 찾을 수 없으므로. 직렬화 중에 잘못된 enum 항목을 무시하거나 건너 뛸 수있는 방법이 있는지 알고 싶습니다. 예외가 발생하지 않고 객체가 직렬화되지 않게됩니다.

+1

내가 작업 예제 프로젝트를 포함하는 링크 된 질문에 대한 내 대답을 참조 할 위치에 당신에게 방법을 최대한 활용해야합니다 http://stackoverflow.com/a/10709040 – user423430

답변

3

Apple을 그대로두고 ObsoleteAttribute으로 표시하십시오. 그런 식으로 Apple을 사용하는 모든 코드는 컴파일러 경고를 생성합니다.

+0

'Apple'열거 형 항목 위에 [Obsolete]를 추가했습니다. 하지만, 난 deserializing 및 이전 개체를 때 여전히 다음 예외가 : 인스턴스 유효성 오류 : '사과'FruitType 유효한 값이 아닙니다. – Elan

0

나는 similar question를 게시했는데, 디시리얼라이저가 XML 파일에서 Apple을 만날 때 던져진 예외를 잡는 간단한 방법을 찾지 못했습니다. 누락 된 특성 또는 요소에 대한 deserialiation 중에 다른 예외를 잡을 수는 있지만 유효하지 않은 enum 값에는 해당되지 않습니다. 잘못된 enum 값 (귀하의 경우 Apple)이 나를 비 직렬화에서 날려 버립니다.

하나의 가능한 솔루션은 과일 클래스에 IXMLSerializable을 구현하는 것입니다. 디시리얼라이저에서 IXMLSerailizable.ReadXML() 메서드를 호출하면 전달되는 내용을 확인해야합니다. 값이 "Apple"인 경우 일부 논리에 따라 열거 형을 GreenApple 또는 RedApple로 설정합니다.

0

필자는 비슷한 대답을 직접 찾고 있었고 XML에 유효하지 않은 열거 형 값이 포함되어있는 경우 예외를 잡으려고이 코드를 작성했습니다. 해당 요소를 제거하고 다시 deserialize를 시도합니다. 요소가 필요한 경우에도 예외가 발생합니다. 그것은 불완전하지만

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; 
    } 
관련 문제