我正在尝试使用.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();
}
答案 0 :(得分:1)
如果通过递归表示遍历对象树,那么是的,当您实现自己的IFormatter时,由您决定。
只需检查属性的值是否为null,以及它是否正在实现IFormatter接口。如果它只是调用它并使用它返回的值。 如果没有,那么它又取决于你:你可能抛出一个异常,说必须实现IFormatter,或者只是回退到某种默认格式化程序(XML或二进制格式化程序)。
递归本身很棘手。比方说,当对象引用自身时,你需要足够聪明来处理这种情况,而不是以无限循环结束:
public class A {
public object SomeProperty { get; set; }
}
var a = new A();
a.SomeProperty = a;
在实现格式化程序时有许多棘手的方面,比如两个属性实际引用同一个对象的情况呢?你会将它序列化/格式化两次或只是一次并以某种方式保存有关这些引用的信息吗? 如果您只想要单向序列化,则可能不需要这样做,但如果您希望能够恢复对象,则可能很重要......