问题
I want do some manipulation on all instances of a CustomType that got created with an XmlSerializer.Deserialize
The best way would be to pass in as a constructor, but "PostSerialization" would work just fine. In this example, I need to pass in an object to my CustomType based from the XmlSerializer context.
public class CustomType : IXmlSerializable
{
public CustomType()
: this(null)
{
}
public CustomType(Object somethingImportant)
{
}
public void ReadXml(System.Xml.XmlReader reader) { ... }
public void WriteXml(System.Xml.XmlWriter writer) { ... }
}
...
Object somethingImportant = 12345; // I need to pass this to *all* CustomType
var serializer = new XmlSerializer(typeof(MyType));
var reader = new StringReader(str);
return serializer.Deserialize(reader) as MyType;
XmlAttributeOverrides is a good idea, but "MyType" is quite complex, I can't go through all the possible XmlElement to custom create the CustomType.
回答1:
You could make the Object somethingImportant
a thread-static variable, and use it in the constructor when non-null, like so:
public class CustomType
{
[ThreadStatic]
static object deserializationObject;
public static IDisposable SetDeserializationObject(object deserializationObject)
{
return new DeserializationObjectValue(deserializationObject);
}
sealed class DeserializationObjectValue : IDisposable
{
object oldValue;
public DeserializationObjectValue(object value)
{
this.oldValue = deserializationObject;
deserializationObject = value;
}
int disposed = 0;
public void Dispose()
{
// Dispose of unmanaged resources.
if (Interlocked.Exchange(ref disposed, 1) == 0)
{
Dispose(true);
} // Suppress finalization. Since this class actually has no finalizer, this does nothing.
GC.SuppressFinalize(this);
}
void Dispose(bool disposing)
{
if (disposing)
{
// Free any other managed objects here.
deserializationObject = oldValue;
oldValue = null;
}
}
}
private CustomType(object deserializationObject)
{
if (deserializationObject != null)
{
// Handle as needed.
}
}
public CustomType() : this(deserializationObject)
{
}
}
Then set it when deserializing like so:
using (CustomType.SetDeserializationObject("this is a runtime value"))
{
var serializer = new XmlSerializer(typeof(MyType));
var reader = new StringReader(str);
var myType = serializer.Deserialize(reader) as MyType;
}
By publicly setting the deserializationObject
only within the disposable wrapper you ensure it's never left around permanently.
来源:https://stackoverflow.com/questions/29438151/execute-code-to-custom-type-after-deserializing-an-object-from-xml