3

我試圖序列化類B作爲它的基類A的實例。 DataContractSerializer不會允許我這樣做。將繼承類型的DataContract序列化爲基類型

一個例子失敗的系列化如下:

class Program 
{ 
    [DataContract] 
    public class A 
    { 
     public int Id { get; set; } 
    } 

    [DataContract] 
    public class B : A 
    { 

    } 


    static void Main(string[] args) 
    { 
     A instance = new B { Id = 42 }; 

     var dataContractSerializer = new DataContractSerializer(typeof(A)); 
     var xmlOutput = new StringBuilder(); 
     using (var writer = XmlWriter.Create(xmlOutput)) 
     { 
      dataContractSerializer.WriteObject(writer, instance); 
     } 

    } 
} 

我知道,這個問題很容易解決通過添加KnownTypes屬性。 但是我想保留從項目中隱藏的類B(不添加引用)。

完全可以實現我想要的嗎?我嘗試了XmlSerializer,但它給了我同樣的問題(它在XML中添加了完整的實例類型名稱),並且使用起來更笨拙。

+0

它必須是XML?或者必須只是工作? – 2010-12-10 16:15:12

+0

它可以工作。儘管最小麻煩會很好。 – R4cOON 2010-12-13 07:37:37

回答

3
[DataContract(Name="YouCannotSeeMyName")] 
[KnownTypes(typeof(B))] 
public class B : A 

,你會得到

<A itype="YouCannotSeeMyName"> 
    ... 
</A> 
+0

我認爲這仍然會序列化B的所有成員,這不是OP的意圖。 – 2010-12-10 15:50:22

+0

@Mark Avenius:如果OP沒有在B的屬性上放置'[DataMember]'屬性,那麼不需要。 – 2010-12-10 15:57:25

+0

優秀點:-) – 2010-12-10 15:59:12

1

我敢肯定,你不能隱藏合同的部分。這類似於處理一個Web服務,在這個Web服務中,爲了理解每個端點如何以及如何進行序列化/反序列化,合同必須得到尊重。

另外,您可以在DataContractSerializer範圍內傳遞B類型,而不使用該屬性。

class Program 
    { 
     [DataContract] 
     public class A 
     { 
      public int Id { get; set; } 
     } 

     [DataContract] 
     public class B : A 
     { 

     } 

     static void Main(string[] args) 
     { 
      A instance = new B { Id = 42 }; 

      var dataContractSerializer = new DataContractSerializer(typeof(A), new List<Type>() { typeof(B) }); 
      var xmlOutput = new StringBuilder(); 
      using (var writer = XmlWriter.Create(xmlOutput)) 
      { 
       dataContractSerializer.WriteObject(writer, instance); 
      } 

     } 
    } 

,這將給你...

<Program.A xmlns:i="http://www.w3.org/2001/XMLSchema-instance" i:type="Program.B" 
xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1" />