递归地实现IFormatter
本文关键字:IFormatter 实现 递归 | 更新日期: 2023-09-27 18:23:42
我正在尝试使用.NET IFormatter接口实现一个自定义格式化程序。
经过几个小时的搜索,我发现了一个非常基本的示例,不幸的是它不包括递归。我还尝试使用Reflector来查看BinaryFormatter和SoapFormatter,但它们相当复杂。
我的问题是:我应该自己实现递归吗,还是在FormatterServices中遗漏了一些内容?
遵循我的代码:
public void Serialize(Stream serializationStream, object graph)
{
// Get fields that are to be serialized.
MemberInfo[] members = FormatterServices.GetSerializableMembers(graph.GetType(), Context);
// Get fields data.
object[] data = FormatterServices.GetObjectData(graph, members);
// Write class name and all fields & values to file
StreamWriter sw = new StreamWriter(serializationStream);
string accumulator = string.Empty;
for (int i = 0; i < data.Length; ++i)
{
// Skip this field if it is marked NonSerialized.
if (Attribute.IsDefined(members[i], typeof(NonSerializedAttribute)))
continue;
FieldInfo field = (FieldInfo)members[i];
if (field.FieldType.IsPrimitive)
{
}
else //TODO: What should I do here?
}
sw.Close();
}
如果递归是指遍历对象树,那么是的,这取决于您在实现自己的IFormatter时。
只需检查属性的值是否不为null,以及它是否正在实现IFormatter接口。如果是,那么只需调用它并使用它返回的值。如果没有,那么这又取决于您:您可能会抛出一个异常,说必须实现IFormatter,或者只是回到某种默认的格式化程序(XML或Binary)。
递归本身是很棘手的。比方说,当对象引用自己时,你需要足够聪明来处理这种情况,而不是以无限循环结束:
public class A {
public object SomeProperty { get; set; }
}
var a = new A();
a.SomeProperty = a;
在实现格式化程序时有很多棘手的方面,比如如果两个属性实际上引用了同一个对象会怎么样?你会序列化/格式化它两次还是一次,并以某种方式保留关于这些引用的信息?如果您只想要单向序列化,则可能不需要此功能,但如果您希望能够恢复对象,则这可能很重要。。。