递归地实现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

如果递归是指遍历对象树,那么是的,这取决于您在实现自己的IFormatter时。

只需检查属性的值是否不为null,以及它是否正在实现IFormatter接口。如果是,那么只需调用它并使用它返回的值。如果没有,那么这又取决于您:您可能会抛出一个异常,说必须实现IFormatter,或者只是回到某种默认的格式化程序(XML或Binary)。

递归本身是很棘手的。比方说,当对象引用自己时,你需要足够聪明来处理这种情况,而不是以无限循环结束:

public class A {
    public object SomeProperty { get; set; }
}
var a = new A();
a.SomeProperty = a;

在实现格式化程序时有很多棘手的方面,比如如果两个属性实际上引用了同一个对象会怎么样?你会序列化/格式化它两次还是一次,并以某种方式保留关于这些引用的信息?如果您只想要单向序列化,则可能不需要此功能,但如果您希望能够恢复对象,则这可能很重要。。。