如何使用DataContractSerializer仅序列化/反序列化基类属性?

时间:2017-01-27 13:28:12

标签: c# .net serialization 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当然不是已知类型。但是我不想将这些额外的信息写入文件,只是基类提供的信息。

1 个答案:

答案 0 :(得分:3)

此解决方案使用反射来获取基类的属性,并在派生类值上设置基类值的新实例。它解决了您当前的问题,但可能无法解决所有问题。

祝你好运,这就是编程的乐趣,我相信你必须修改一些!

    [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;
    }