2017-01-27 11 views
1

宣言されたタイプのプロパティのみをシリアル化およびデシリアライズする最も単純な方法は、実際のオブジェクトが宣言されたものよりも派生しているという事実を無視していますか?これらのクラスとインスタンスの場合:DataContractSerializerで基本クラスのプロパティのみをシリアル化/逆シリアル化する方法

[DataContract] 
public class Base 
{ 
    [DataMember] 
    string BaseProperty { get; set; } 
} 

public class Derived : Base 
{ 
    string DerivedProperty { get; set; } 
} 

私はこれと同等のものを達成できるようにしたいと思います:

Base baseObject = new Derived(); 
var baseSerializer = new DataContractSerializer(typeof(Base)); 

using (var fileStream = File.OpenWrite("file")) 
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(fileStream)) 
{ 
    baseSerializer.WriteObject(writer, baseObject); 
} 

using (var fileStream = File.OpenRead("file")) 
using (var reader = XmlDictionaryReader.CreateBinaryReader(fileStream, new XmlDictionaryReaderQuotas())) 
{ 
    var deserialized = (Base)baseSerializer.ReadObject(reader); 
} 

提供されるサンプルコードは失敗しDerivedはもちろん、既知のタイプではないので。しかし、私は追加情報をファイルに書き込むことに興味はなく、ベースクラスが提供するものだけに興味があります。

+0

'KnownTypeAttribute'をどこかに追加する必要はありませんか? https://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute(v=vs.110).aspx – Michael

+0

これは、リストに 'Derived 'を単に追加することで動作することができます既知のタイプのもの。しかし、私は明らかにこれをしたくありません。私は実際のオブジェクトが単純な 'Base'ではないという事実を無視したいと思います。 –

+0

XmlDictionaryWriterは型情報を保存する傾向があります。 JSONなどのデフォルトタイプのサポートなしでシリアライザを使用するだけです。 Newtonsoft.JSONでは、シリアライズ契約を指定して、シリアライズするものと一般的でないものを指定することができます。 – eocron

答えて

2

このソリューションは、リフレクションを使用してベースクラスのプロパティを取得し、ベースクラス値の新しいインスタンスを派生クラス値に設定します。現在の問題を解決しますが、すべての問題を解決するわけではありません。

最高の運が、それはプログラミングの楽しさです、私はあなたがこのいくつかを修正する必要があると確信しています!

[DataContract] 
    public class Base 
    { 
     [DataMember] 
     string BaseProperty { get; set; } 

     public void SetBase(string val) 
     { 
      BaseProperty = val; 
     } 
    } 

    public class Derived : Base 
    { 
     public Derived() 
     { 
      SetBase("TestWorks"); 
     } 

     string DerivedProperty { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     var obj = new Derived(); 

     Base baseObject = GetBaseObject<Base, Derived>(obj); 

     var baseSerializer = new DataContractSerializer(typeof(Base)); 

     using (var fileStream = File.OpenWrite("file")) 
     using (var writer = XmlDictionaryWriter.CreateBinaryWriter(fileStream)) 
     { 
      baseSerializer.WriteObject(writer, baseObject); 
     } 

     using (var fileStream = File.OpenRead("file")) 
     using (var reader = XmlDictionaryReader.CreateBinaryReader(fileStream, new XmlDictionaryReaderQuotas())) 
     { 
      var deserialized = (Base)baseSerializer.ReadObject(reader); 
     } 
    } 

    public static TBase GetBaseObject<TBase, T>(T obj) where TBase : new() where T : TBase 
    { 
     TBase bObj = new TBase(); 

     var bProps = bObj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public); 

     foreach (var bProp in bProps) 
     { 
      bProp.SetValue(bObj, 
       obj.GetType().BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) 
       .First(p => p.Name == bProp.Name).GetValue(obj)); 
     } 

     return bObj; 
    } 
関連する問題