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

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

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

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

protobuf-net有一个Serializer.Merge方法,可以反序列化为现有实例。 仅写入在流中找到的值(它不会擦除对象)。

不是微软,但相当稳定。

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

您可以使用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); 

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

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