【问题标题】:How to serialize/deserialize only base class properties with DataContractSerializer?如何使用 DataContractSerializer 仅序列化/反序列化基类属性?
【发布时间】:2017-01-27 13:28:12
【问题描述】:

什么是仅序列化和反序列化声明的属性类型的最简单方法,而忽略实际对象的派生多于声明的事实?例如,对于这些类:

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

【问题讨论】:

  • 您不需要在某处添加KnownTypeAttribute 吗? msdn.microsoft.com/en-us/library/…
  • 我知道这可以通过简单地将Derived 添加到已知类型列表中来实现。但我明确不想这样做。我想忽略一个事实,即实际对象不是一个简单的Base。
  • XmlDictionaryWriter 倾向于保存类型信息。只需使用没有默认类型支持的序列化程序,例如 JSON。在 Newtonsoft.JSON 中,您可以指定序列化合约,您可以在其中指定要序列化的内容以及一般不应该序列化的内容。
  • 使用 DataContractSerializer 重要吗?否则,您可以尝试使用 XmlSerializer,它无需所有额外的符号即可工作。
  • @user1628733 - 是的,您的回答很有意义。沿着同样的思路,可以使用automapper 之类的东西将派生类映射到基类。但是如果他们从不需要序列化派生属性,那么一些捷径是可能的。

标签: c# .net serialization datacontractserializer


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多