C # .NET Loading / unloading an assembly while maintaining the same session

I am new to C # and .NET and am trying to create an asp.net web application that dynamically loads an assembly.

I originally used Activator.CreateInstance to dynamically load assemblies, but it seems to block the assembly of the DLL file. As I make frequent changes to the assembly, this becomes quite a pain. I also need to share the assembly with other applications, so it can become a problem later.

Most people seem to recommend creating a separate AppDomain and loading the assembly into it, and then unloading the appdomain after completion. However, my application and assembly also depend on the context of the session, and the entire session is lost as soon as I submit it to the application domain; Failures fail because it cannot find the session context.

Is there a way to pass my session context to AppDomain? Or is there a way to load an assembly without locking the DLL file? I tried streaming the file like some of them, but it still blocks the dll.

Edit: I tried the following code as David Piras suggested, but the dll file is still locked

  private static T CreateInstance<T>(string fileName, string typeName) { if (!File.Exists(fileName)) throw new FileNotFoundException(string.Format("Cannot find assembly '{0}'.", fileName)); try { Assembly assembly = Assembly.LoadFrom(fileName); if (assembly != null) { List<Type> assemblyTypes = assembly.GetTypes().ToList(); Type assemblyType = assemblyTypes.FirstOrDefault(asmType => typeof(T).IsAssignableFrom(asmType)); T instance = (T) Activator.CreateInstance(assemblyType); if (instance != null) return instance; } // Trouble if the above doesn't work! throw new NullReferenceException(string.Format("Could not create type '{0}'.", typeName)); } catch (Exception exp1) { throw new Exception("Cannot create instance from " + fileName + ", with type " + typeName + ": " + exp1.Message + exp1.Source, exp1.InnerException); } } 
+4
source share
1 answer

To load assemblies in the same AppDomain but not block files after loading, simply use the LoadFrom method as follows:

 Assembly asm = Assembly.LoadFrom( "mydll.dll" ); 

that way you’ll end and the session will be available.

there will be a problem with the debugger, because the characters (* .pdb) will not be loaded, so there is no breakpoint and no debugging, in order to be able to debug you, you really need to load .pdb files into memory, for example using FileStream.

Edit:. How you can make it so that the characters are loaded and not blocked, you need to use the appropriate Assembly.Load overload, which receives two bytes [] for the assembly and another for the assembly's symbol file (.pdb file):

 public static Assembly Load( byte[] rawAssembly, byte[] rawSymbolStore ) 

in fact, you must first load the bytes with the stream, and then call Assembly.Load and pass the byte []

EDIT 2:

here is a complete example of loading assemblies in your current domain, including a symbol file and no file locking.

this is a complete example found on the web, it reflects everything you need, including handling AppDomain.AssemblyResolve ...

 public static void Main() { AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolver); } static void InstantiateMyType(AppDomain domain) { try { // You must supply a valid fully qualified assembly name here. domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyType"); } catch (Exception e) { Console.WriteLine(e.Message); } } // Loads the content of a file to a byte array. static byte[] loadFile(string filename) { FileStream fs = new FileStream(filename, FileMode.Open); byte[] buffer = new byte[(int) fs.Length]; fs.Read(buffer, 0, buffer.Length); fs.Close(); return buffer; } static Assembly MyResolver(object sender, ResolveEventArgs args) { AppDomain domain = (AppDomain) sender; // Once the files are generated, this call is // actually no longer necessary. EmitAssembly(domain); byte[] rawAssembly = loadFile("temp.dll"); byte[] rawSymbolStore = loadFile("temp.pdb"); Assembly assembly = domain.Load(rawAssembly, rawSymbolStore); return assembly; } 
+4
source

All Articles