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 System;

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 fields

Type 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 required

xmlSerializerTemporaryAssembly = (Assembly)xmlSerializerTemporaryAssemblyUntyped.GetType().InvokeMember(

"assembly"

, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField

, null

, xmlSerializerTemporaryAssemblyUntyped

, null

);

// Debug

// Console.WriteLine("xmlSerializerAssembly.Location = {0}", xmlSerializerTemporaryAssembly.Location);

return xmlSerializerTemporaryAssembly;

}

}

}

 

1 Comment

  • I actually thought about adding that functionality but I didn't think anybody would actually use it. Or there are times when a number of classes are not meant to be serialized. I will take a look at adding it in a subsequent release.

    -Mathew Nolton

Comments have been disabled for this content.