递归地实现IFormatter

时间:2012-02-07 09:53:14

标签: c# serialization

我正在尝试使用.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();
}

1 个答案:

答案 0 :(得分:1)

如果通过递归表示遍历对象树,那么是的,当您实现自己的IFormatter时,由您决定。

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

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

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

在实现格式化程序时有许多棘手的方面,比如两个属性实际引用同一个对象的情况呢?你会将它序列化/格式化两次或只是一次并以某种方式保存有关这些引用的信息吗? 如果您只想要单向序列化,则可能不需要这样做,但如果您希望能够恢复对象,则可能很重要......