将属性反序列化为预先存在的对象

时间:2010-02-26 12:38:43

标签: c# serialization

是否可以使用任何标准序列化程序反序列化对象属性,而无需创建新对象?

问题是,有问题的对象非常复杂(它们只能由特殊工厂创建,它们的类型是在运行时动态生成的),但是它们有一些已知的属性,我想将它们存储在外部文件中(最好是xml,但二进制也可以),以后(可能在应用程序重启后),我希望将存储的属性设置回我提供的对象。

似乎所有标准序列化程序只能为我生成一个新对象(这也需要一个公共无参数构造函数),我必须从中手动分配所有属性。这与我希望避免的手动序列化没有太大区别,因为一组序列化属性非常大,并且在项目生命周期中可能会改变几次。在这一点上,我非常接近编写自己的轻量级序列化器,但也许有人可以提出一种更标准的方法来做这些事情?

4 个答案:

答案 0 :(得分:3)

protobuf-netSerializer.Merge方法,可让您反序列化为现有实例。只写入流中找到的值(它不会擦除对象)。

不是微软,但相当稳定。

扩展这个;获得处理所有常见场景的强大序列化(我从痛苦的经历中得知)很多工作。我的建议肯定是尽可能重用现有的代码。 protobuf-net似乎提供了你需要的一切;当前的二进制文件只需要你装饰你的类(非常类似于WCF中的[DataContract] - 实际上它甚至支持[DataContract] / [DataMember]),但是工作已经到位以便它可以工作即使是针对POCO - 所以你可以使用不受你控制的类型。

答案 1 :(得分:2)

您可以使用FormatterServices课程。

你有一本课程书:

[Serializable]
class Book
{
    public string Title { get; set; }

    public string Author { get; set; }

    // Constructor for setting new values. 
    public Book(string title, string author)
    {
        Title = title;
        Author = author;
    }
}

您可以像这样序列化:

var book = new Book("Moby Dick", "Herman Melville");

string path = Path.GetTempFileName();

var bf = new BinaryFormatter();
using (var fs = new FileStream(path, FileMode.Create))
    bf.Serialize(fs, book);

如果您的对象被修改:

// Edit object
book.Title = "Foo";
Console.WriteLine("{0}, {1}", book.Title, book.Author);

您可以使用以下代码恢复它:

Book temp;
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
    temp = (Book) bf.Deserialize(fs);

MemberInfo[] members = FormatterServices.GetSerializableMembers(typeof (Book));
FormatterServices.PopulateObjectMembers(book, members, FormatterServices.GetObjectData(temp, members));

// Object state is back
Console.WriteLine("{0}, {1}", book.Title, book.Author);

答案 2 :(得分:0)

您可以实现自己灵活的“序列化程序”来处理此问题。 Reflection为您提供所需的一切。

答案 3 :(得分:0)

您可以使用FormatterServices.PopulateObjectMembers方法,这似乎是为此任务设计的......