Uploading assemblies to another AppDomain and Type inspection

I am trying to load assemblies in another appdomain (to be able to unload them when it is not needed), but I also want to be able to check types in a loaded assembly and create instances of my types (via Activator). Also, I do not want assemblies to be locked at boot time.

I do not understand how this is possible. Things I tried:

  • Loading Assembly.Load (File.ReadAllBytes (path)) helps me load the assembly without locking it, so it can be deleted / moved. This loads the assembly into the current appdomain, so it cannot be unloaded.

  • Creating another AppDomain and using AppDomain.Load () loads the assembly into the new AppDomain, but it is not possible to check all types found in the loaded AppDomain. I can’t create anything unless I know the type of the fully qualified type name, and even then they must be either Serializable or derived from MarshallByRef. Another AppDomain product works through Proxies, so creating things is easier without having a Contract / Common interface, etc.

  • MEF also loads assemblies into the current AppDomain, so it basically does the same.

  • Mono.Cecil allows you to check the type on a loaded assembly, but then I can not create types using TypeReference. Maybe if there was a way to convert TypeReference to Type?

I checked how ILSpy does this, and without any surprises, it uses Mono.Cecil to load / unload the assembly, but again, it does not instantiate any types, it just checks the type that is possible through Mono.Cecil.

Now the question is, is this possible? Did I miss something?

+4
source share
1 answer

If you load the assembly into another appdomain, you should of course create instances there and use them there. Other than that, I'm not sure what the problem is that you are facing.

Update

  • added code to select a type from the list
  • changed only to package type names in domains as strings

using System; using System.IO; using System.Reflection; using System.Runtime.Remoting; public class MainClass : MarshalByRefObject { static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("usage: {0} assembly", Path.GetFileName(Assembly.GetExecutingAssembly().Location)); return; } AppDomain other = AppDomain.CreateDomain("other"); Type myType = typeof(MainClass); // create a loader instance in the new domain MainClass loader = (MainClass)other.CreateInstanceAndUnwrap(myType.Assembly.FullName, myType.FullName); string assemblyName; string[] types = loader.LoadAssembly(args[0], out assemblyName); Console.WriteLine("Loaded assembly {0}.", assemblyName); Console.WriteLine("Types:"); for(int i = 0; i < types.Length; i += 1) { Console.WriteLine("[{0}] {1}", i, types[i]); } Console.Write("Enter index of type to create, -1 to exit: "); int create = Int32.Parse(Console.ReadLine()); if (create < 0) { return; } Console.WriteLine("Creating instance of type {0}", types[create]); Console.WriteLine("Type of the created instance was: {0}", loader.CreateInstance(assemblyName, types[create])); } string[] LoadAssembly(string path, out string assemblyName) { Console.WriteLine("LoadAssembly executing in appdomain {0}", AppDomain.CurrentDomain.FriendlyName); Assembly assembly = Assembly.Load(File.ReadAllBytes(path)); assemblyName = assembly.FullName; return Array.ConvertAll<Type, string>(assembly.GetExportedTypes(), x => x.FullName); } string CreateInstance(string assemblyName, string typeName) { Console.WriteLine("CreateInstance executing in appdomain {0}", AppDomain.CurrentDomain.FriendlyName); object instance = Activator.CreateInstance(assemblyName, typeName).Unwrap(); // do something useful with the instance here return instance.GetType().FullName; } public override object InitializeLifetimeService() { return null; } } 

Sample output for log4net.dll :

 $ mono main.exe log4net.dll LoadAssembly executing in appdomain other Loaded assembly log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=a5715cc6d5c3540b. Types: [0] log4net.Core.SecurityContext [1] log4net.Core.LoggerWrapperImpl [2] log4net.Core.LogImpl [3] log4net.Core.DefaultRepositorySelector ... [160] log4net.Appender.AspNetTraceAppender [161] log4net.Appender.FileAppender ... [197] log4net.Repository.LoggerRepositoryConfigurationResetEventHandler [198] log4net.Repository.LoggerRepositoryConfigurationChangedEventHandler Enter index of type to create, -1 to exit: 161 Creating instance of type log4net.Appender.FileAppender CreateInstance executing in appdomain other Type of the created instance was: log4net.Appender.FileAppender 
+1
source

All Articles