Freigeben über


.Net Reflection and Unloading Assemblies

I was working with one of our tools and ran into the following problem. The tool is on the PATH environment variable and we run it from different folders (through the console). On those folders the tool builds an assembly, loads it through reflection and then does some operations against it. Now the issue is that if I’m doing the build and load thing multiple times the assembly is locked and I can’t rebuild it (failures due to a sharing violation).

                I though ok, this should be easy enough, just call Assembly.Unload right? Well to my surprise there’s no such method. After doing some research I found there’s an unload method if you’re using AppDomain and I got all excited. Unfortunately that didn’t last long as I had to use AppDomain.Load and due to the path issue I mentioned above Load would just fail. The loading of the assembly was being done though Assembly.LoadFrom to get around the path issue.

The whole process of trial an error lasted a few hours and I probably lost a few hairs but experimenting with the Assembly.Load overloads I saw one that took a byte array and some light bulbs started flashing above my head. Using that overload solved two issues:

- I could load the assembly no matter the path because I was getting it in memory first (inside the byte array)

- Since I was loading it in memory and loading that memory buffer the file wasn’t getting locked so that fixed my original issue.

String filename = …; // Full path of the assembly I want to load

byte[] file = null;

int bufferSize = 1024;

using (FileStream fileStream = File.Open(filename, FileMode.Open))

{

using (MemoryStream memoryStream = new MemoryStream())

       {

       byte[] buffer = new byte[bufferSize];

       int readBytesCount = 0;

       while ((readBytesCount = fileStream.Read(buffer, 0, bufferSize)) > 0)

       memoryStream.Write(buffer, 0, readBytesCount);

              file = memoryStream.ToArray();

       }

}

Assembly assembly = Assembly.Load(file);

Comments

  • Anonymous
    January 28, 2015
    This will do same thing with a lot less to read Assembly processLibrary = Assembly.Load(File.ReadAllBytes(filename));

  • Anonymous
    March 13, 2016
    Gracias -> Assembly.Load(File.ReadAllBytes(filename));