2014-10-17 2 views
0

전달 된 형식이 serializer가 만들어 졌을 때의 형식과 일치하지 않으면 XmlSerializer이 예외를 throw합니다.XML은 파생 클래스를 모르는 상태에서 기본 클래스를 serialize합니다.

제 질문은 : 파생 형식을 모른 채 기본 형식을 serialize 할 수 있습니까?

다음 클래스가 최상위 도메인에 있고 몇하거나 종속되지 :이 시나리오를 고려

public class Serializer 
{ 
    private static string Serialize(Base baseData) 
    { 
     var serializer = new XmlSerializer(typeof(Base)); 
     var sb = new StringBuilder(); 
     using (var writer = XmlWriter.Create(sb)) 
     { 
      serializer.Serialize(writer, baseData); 
     } 
     return sb.ToString(); 
    } 

    private static string Deserialize(...) { ... } 
} 

public class Base 
{ 
    public string Name { get; set; } 
} 

다음 파생 클래스 추가 종속성 UI 구성 요소 같은 것들에를 조성은 등 (이 나중에 이상) :

[Export(typeof(IMyComponent))] 
public class Derived : Base, IMyComponent, INotifyPropertyChanged 
{ 
    public new string Name 
    { 
     get { return base.Name; } 
     set 
     { 
      base.Name = value; 
      NotifyPropertyChanged("Name"); 
     } 
    } 
} 

이 같은 시리얼 호출 할 경우

,369을
Base myData = new Derived(); 
myData.Name = "Foo bar"; 
Serializer.Serialize(myData); 

매개 변수 및 serializer가 명시 적으로 Base으로 설정되어 있어도 Derived을 전달했기 때문에 예외가 발생합니다. 내가 원하는 건 Base을 직렬화하는 것입니다. 무엇이든 상관 없어요. Derived.

여기 내 목표는 UI를 사용하여 파생 클래스를 만드는 것이지만 은 기본 클래스 만 serialize합니다. 그 이유는 .NET 프레임 워크 외의 추가 종속성을 포함해서는 안되는 별도의 어셈블리에서 XML을 deserialize하고 있기 때문입니다. serializer 및 기본 개체를이 격리 된 어셈블리에 다시 만들고 복사하여 네임 스페이스와 형식이 일치하도록합니다. 따라서 역 직렬화가 발생할 때 형식이 올바르게 deserialize됩니다. 하지만 Derived의 사본을 포함 할 수 없습니다. UI, MEF, 타사 라이브러리 등에 종속되어 있기 때문에 포함시킬 수 없습니다.

그래서 파생 클래스에서 전달하는 경우에도 serializer가 serialize하도록 강제 할 수 있습니까? 수업? 다시 말하지만, 내가 Derived에있는 정보를 잃어 버릴지라도 걱정하지 않아도됩니다. 걱정되는 것은 모두 Base입니다.

답변

1

,이 자료의 인스턴스를 생성하고 파생 된 유형의 속성을 매핑해야합니다. 시리얼 라이저는 똑똑하고, 때로는 너무 스마트하게 프로그래밍됩니다.

AutoMapper를 살펴 보거나 수동으로 수행하십시오.

public class Serializer 
{ 
    private static string Serialize(Base baseData) 
    { 
     var mappedBase = new Base(); 
     // Do mapping 
     mappedBase.Foo = baseData.Foo; 

     var serializer = new XmlSerializer(typeof(Base)); 
     var sb = new StringBuilder(); 
     using (var writer = XmlWriter.Create(sb)) 
     { 
      serializer.Serialize(writer, mappedBase); 
     } 
     return sb.ToString(); 
    } 

    private static string Deserialize(...) { ... } 
} 
+0

이것은 기본적으로 파생 클래스를 기본 클래스의 새 인스턴스에 매핑하는 것입니다. 가장 좋은 솔루션은 아니지만 작동합니다. 감사! – qJake

1

한 가지 가능한 해결책은 다음과 같습니다 당신은 단지 기본 속성을 직렬화 찾고 있기 때문에

public class Serializer 
{ 
    public static string Serialize(Base baseData) 
    { 
     var baseType = baseData.GetType().BaseType; 
     var baseTypeFieldInfo = baseType.GetProperties(); 
     var newBaseInstance = new Base(); 
     var newBaseInstanceType = newBaseInstance.GetType(); 
     //ONLY gets public properties but could be applied to fields 
     var newBaseTypeFieldInfo = newBaseInstanceType.GetProperties(); 
     foreach (var bt in baseTypeFieldInfo) 
     { 
      foreach (var nbt in newBaseTypeFieldInfo) 
      { 
       if (nbt.Name == bt.Name) 
       { 
        nbt.SetValue(newBaseInstance, bt.GetValue(baseData, null), null); 
       } 
      } 
     } 
     var serializer = new XmlSerializer(typeof(Base)); 
     var sb = new StringBuilder(); 
     using (var writer = XmlWriter.Create(sb)) 
     { 
      serializer.Serialize(writer, newBaseInstance); 
     } 
     return sb.ToString(); 
    } 
} 

public class Base 
{ 
    public string Name { get; set; } 
} 


public class Derived : Base 
{ 

    public string AnotherName { get; set; } 

    public new string Name 
    { 
     get { return base.Name; } 
     set { base.Name = value; } 
    } 
} 
+0

불행히도 내 'Base'와 'Derived'는 분리되어야합니다. 'Base'는'Derived '에 대해 아무것도 알 수 없습니다. – qJake

+0

확인. 나는 약간의 성찰을 사용하기 위해 편집했다. 이것은 StackOverflow에 대한 두 번째 게시물입니다.이 질문은 답변을 편집하는 올바른 방법이 아니므로 다시 읽을 것입니다. –

+0

나는 기본적으로 TyCobb의 대답을 구현 한 것입니다. –

관련 문제