如何使用 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不是已知类型。但是我对将附加信息写入文件不感兴趣,只对基类提供的内容感兴趣。

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

祝你好运,这就是编程的乐趣,我相信你将不得不对此进行一些修改!

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

最新更新