有没有办法找出对象属性是否作为DeSerialization过程的一部分被调用(例如XmlSerializationReaderXXX
)。
背景:典型的情况是在这种情况下禁用事件和复杂操作,直到初始化完成。
我发现的一种方法是“解释”堆栈并查看调用是否由XmlSerializationReaderXXX
触发,这不是那么优雅的恕我直言。还有什么更好的吗?
public SomeClass SomeProperty
{
get { ..... }
set
{
this._somePropertyValue = value;
this.DoSomeMoreStuff(); // Do not do this during DeSerialization
}
}
- 更新 -
正如Salvatore所提到的,某种程度上类似于How do you find out when you've been loaded via XML Serialization?
答案 0 :(得分:3)
我有一个可能的解决方案。
public class xxx
{
private int myValue;
[XmlElement("MyProperty")]
public int MyPropertyForSerialization
{
get { return this.myValue; }
set
{
Console.WriteLine("DESERIALIZED");
this.myValue = value;
}
}
[XmlIgnore]
public int MyProperty
{
get { return this.myValue; }
set
{
Console.WriteLine("NORMAL");
this.myValue = value;
}
}
}
class Program
{
static void Main(string[] args)
{
xxx instance = new xxx();
instance.MyProperty = 100; // This should print "NORMAL"
// We serialize
var serializer = new XmlSerializer(typeof(xxx));
var memoryStream = new MemoryStream();
serializer.Serialize(memoryStream, instance);
// Let's print our XML so we understand what's going on.
memoryStream.Position = 0;
var reader = new StreamReader(memoryStream);
Console.WriteLine(reader.ReadToEnd());
// Now we deserialize
memoryStream.Position = 0;
var deserialized = serializer.Deserialize(memoryStream) as xxx; // This should print DESERIALIZED
Console.ReadLine();
}
}
诀窍是使用XmlIgnore,它将强制xml序列化程序忽略我们的属性,然后我们使用XmlElement重命名属性以使用我们想要的属性的名称进行序列化。
这种技术的问题在于你必须公开一个公共属性进行序列化,并且在某种程度上是不好的,因为它几乎可以被所有人调用。 如果该成员是私人的,那将是行不通的。
它有效,并不完全干净,但是线程安全且不依赖任何旗帜。
另一种可能性是使用Memento模式之类的东西。 使用相同的技巧,您可以添加一个名为Memento的属性,该属性返回另一个包含仅适用于序列化的属性的对象,它可以使事情变得更加清晰。
您是否认为不改变方法并使用DataContractSerializer?它功能更强大,可以生成纯XML。它支持OnDeserializationCallback机制。
答案 1 :(得分:2)
由于你有一个相当复杂的场景,你可能想要考虑创建一个“数据核心”类,它将使用简单的直接方式实际序列化/反序列化。然后,您的复杂对象将从该对象构造,并正常触发所有事件/操作。它会产生反序列化的序列 - >火灾事件/操作更明确,更容易理解。
答案 2 :(得分:1)
有一个OnDeserializingAttribute
/ OnDeserializedAttribute
属性对。您可以在反序列化对象时设置isDeserializing
标志。不过,我不知道他们是否能很好地使用XML序列化。
答案 3 :(得分:1)
对于XML序列化解决方案可以实现IXmlSerializable并将此类逻辑嵌入ReadXml()/WriteXml()
方法
答案 4 :(得分:1)
为了更好地控制反序列化过程,您可以为SomeClass
实现IXmlSerializable
interface - 在ReadXML
中,您可以为某个字段设置一个标记,您正在进行反序列化。然后可以在相应的方法中检查此标志......并且在完成时需要重置它。
另一个选择(虽然不适用于XML IIRC)是通过OnDeserializingAttribute
和OnDeserializedAttribute
来实现上述内容。
答案 5 :(得分:0)
我最初误解了这个问题,但是你想在setter中询问你是否在反序列化期间被调用。为此,请使用静态标志:
[serializable]
class SomeClass
{
public static IsSerializing = false;
SomeProperty
{
set
{
if(IsSerializing) DoYouStuff();
}
}
}
然后在序列化之前设置标志:
try
{
SomeClass.IsSerializing = true;
deserializedClass = (SomeClass)serializer.Deserialize(reader);
}
finaly
{
SomeClass.IsSerializing = false; //make absolutely sure you set it back to false
}
请注意,即使您反序列化包含类成员的类,相同的方法也可以工作...
答案 6 :(得分:0)
在属性上设置断点,并以调试模式运行。它将在您设置断点的getter / setter的访问点处中断。