Access the XmlSerializer Temporary Assembly
I've been using the excellent XmlPreCompiler - GUI by Mathew Nolton, original idea by Chris Sells. My own idea was to extend the GUI to allow me to verify Types in a batch. For example, I sometimes want to check every Type in an Assembly. I have a basic implementation of that idea now. However, the side-effect of this feature is that, if run against an Assembly with hundreds of Types, I end up with literally thousands of files dumped in the "Documents and Settings" area on the hard disk; each XmlSerializer instance generates several temporary files. I then wondered whether I could clean-up these files after a check had been run. Several files are created, all with the same unique file name prefix. However, the XmlSerializer does not expose the details of the temporary Assembly it creates. It turns out, though, that use of Reflection can get the desired result. Here is a simple Helper class, that will return the temporary Assembly from an XmlSerializer instance. Incidentally, my initial experience suggests that the temporary Assembly cannot be deleted in the same session of the XmlPreCompiler - I see AccessViolationExceptions. Perhaps the cleanup must occur in the next session, after the files have been released by the application? using
using
System.Reflection;using
System.Xml.Serialization;namespace
XmlPreCompiler{
/// <summary> /// Summary description for XmlSerializerAssemblyHelper. /// </summary> public class XmlSerializerAssemblyHelper{
public XmlSerializerAssemblyHelper(){
// // TODO: Add constructor logic here //}
public static Assembly GetTemporaryAssemblyFromXmlSerializer(XmlSerializer xmlSerializer){
if (null == xmlSerializer){
throw new ArgumentNullException("xmlSerializer");}
Assembly xmlSerializerTemporaryAssembly =
null; // Use Reflection to access private fieldsType xmlSerializerType = xmlSerializer.GetType();
// tempAssembly is the NonPublic Instance Field required // tempAssembly has a NonPublic Type = TempAssembly // Therefore, assign the result to the catch-all object Type object xmlSerializerTemporaryAssemblyUntyped = xmlSerializerType.InvokeMember("tempAssembly"
, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField
,
null, xmlSerializer
,
null);
// Debug // Console.WriteLine("xmlSerializerTemporaryAssemblyUntyped.GetType.Name = {0}", xmlSerializerTemporaryAssemblyUntyped.GetType().Name); // Use Reflection to access private fields // assembly is the NonPublic Instance Field requiredxmlSerializerTemporaryAssembly = (Assembly)xmlSerializerTemporaryAssemblyUntyped.GetType().InvokeMember(
"assembly"
, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField
,
null, xmlSerializerTemporaryAssemblyUntyped
,
null);
// Debug // Console.WriteLine("xmlSerializerAssembly.Location = {0}", xmlSerializerTemporaryAssembly.Location); return xmlSerializerTemporaryAssembly;}
}
}