none
Dynamic Assembly Loading / Unloading RRS feed

  • General discussion

  •  

         Hi everyone. Let me start off with a few basic statements. I am in no way new to MSDN; however, I have never posted on the forums. I usually like to stay low and see what other people have said or think. I tend to develop a lot of applications anywhere from controls applications (Microcontrollers) to .NET applications. Anyhow.. here is my discussion topic.

    I am in no way here to start another "OMG, how do I unload assemblies in the current app domain" question or topic, so anybody who reads what I am about to propose, and says its impossible, please refrain from posting. I am seriously sick of hearing all of the "its impossible" talk. I am a person who tends to try and take the impossible and make it possible. With that said, I have recently come upon the need for unloading assemblies in the current app domain. Loading assemblies in another app domain and unloading it when not using them will not cut it, nor does trying to pass object between domains cut it. For example, one of the applications is dynamic loading / unloading WPF plugins via assembly dlls and making the UI extensible. Now.. we can try to apply the seperate app domain for every plugin approach to this situation, but for one... there are remoting issues. For two, it is my understanding that each app domain starts its own thread / UI thread (WPF app domain plugin), therefore if there were tens of plugins... you would have tens of UI threads. Extremely wasteful. There is no easy way to copy objects by reference to other app domains either using remoting or not using it.

    Where am I going with this? Well.. in .NET4, Microsoft introduced collectible assemblies. These things allow you to define a dynamic assembly at runtime using reflection emit. So technically I can load and unload an assembly in the same app domain! Exactly what I want. Quick and easy. Whats the catch? Oh yeah.. Microsoft forgot to put in a LoadFromAssemblyFile function. This means if I already have compiled code, say from a WPF plugin that someone made (.dll file), I have no way of loading it in the dynamic assembly I just created. How to solve this issue? I have looked at many many things, and they are either impossible to do because the CLR is not open source, or they are just too time consuming. I would be an old fool by the time I got something working. Well.. I didnt just decide to post this message here intending to say "its impossible". The third option is:

    Writing an assembly CLR PE loader. I am currently undertaking the task of writing such a loader that will parse a pure IL CLR .dll assembly file. The loader will parse namespaces, classes, fields, etc. and load them into the dynamic assembly. Once the dynamic assembly is loaded, it can be used just like any other dynamic assembly that is loaded at runtime. Wouldn't it be awesome if you could write the following code?:

     

     

    using System;
    using System.Awesome;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace Program
    {
     public class AppStart
     {
     public static void Main(string[] args)
     {
     int result = 0;
    
     // Load dynamic assembly from filename TestAssembly.dll
     // in same directory as this application.
     DynamicAssembly assembly = DynamicAssembly.Load("TestAssembly");
    
     // Call a static function in the assembly.
     // This function is a static function that adds two numbers
     // and returns the result.
     result = (int)assembly.Execute("Test.TestClass.AddTwoNumbers", new object[] { 42, 77 });
    
     // Print out the result and the current assemblies
     // in this application domain
     Console.WriteLine(result);
     PrintAssemblies();
    
     // Let us now UNLOAD the assembly
     DynamicAssembly.Unload(assembly);
     Console.WriteLine("\n\n");
    
     // Print out the new list of assemblies in the
     // application domain
     PrintAssemblies();
     }
    
     private static void PrintAssemblies()
     {
     Assembly[] assms = AppDomain.CurrentDomain.GetAssemblies();
    
     foreach (Assembly a in assms)
     {
     Console.WriteLine(a.GetName().Name);
     }
     }
     }
    }
    

     

    Here's a screen of that code running.http://postimage.org/image/vho0yu04/. Of course... as of right now, the add function is "virtually implemented". That code is not loaded from the assembly file. Additionally, "Dynamic Assembly" in the list refers to the running application exe, which is named Dynamic Assembly. This is simply a unit test. I'm not done with the PE loader. Anyhow... I believe that it should be and is possible to do something of this nature. Again, this would support PURE .NET IL assemblies. I'll be damned if I am going to dabble in mixed or native assemblies. So... I would like to hear people's CONSTRUCTIVE thoughts on this subject. If you plan on attacking me outright for whatever reason.. (I have had that experience more than once, because I post so little), do not bother posting. I realize that it will take time and effort to perfect.

     

     LostTime77



     




    Sunday, July 24, 2011 6:38 AM

All replies

  • Hi,

    Looks like interesting work.

    Maybe you can take a look at the CECIL library - they can read and write assemblies, this could save you lots of hassles for reading the assemblies.

     

    HTH,

    Markus

    Sunday, July 24, 2011 12:21 PM
  • hi,  Why can't I find DynamicAssembly ?


    Regards

    John Huang, MVP-SQL, MCM-SQL, http://www.sqlnotes.info

    Saturday, June 9, 2012 8:25 AM
  •      Hi everyone. Let me start off with a few basic statements. I am in no way new to MSDN; however, I have never posted on the forums. I usually like to stay low and see what other people have said or think. I tend to develop a lot of applications anywhere from controls applications (Microcontrollers) to .NET applications. Anyhow.. here is my discussion topic.

    I am in no way here to start another "OMG, how do I unload assemblies in the current app domain" question or topic, so anybody who reads what I am about to propose, and says its impossible, please refrain from posting. I am seriously sick of hearing all of the "its impossible" talk. I am a person who tends to try and take the impossible and make it possible. With that said, I have recently come upon the need for unloading assemblies in the current app domain. Loading assemblies in another app domain and unloading it when not using them will not cut it, nor does trying to pass object between domains cut it. For example, one of the applications is dynamic loading / unloading WPF plugins via assembly dlls and making the UI extensible. Now.. we can try to apply the seperate app domain for every plugin approach to this situation, but for one... there are remoting issues. For two, it is my understanding that each app domain starts its own thread / UI thread (WPF app domain plugin), therefore if there were tens of plugins... you would have tens of UI threads. Extremely wasteful. There is no easy way to copy objects by reference to other app domains either using remoting or not using it.

    Where am I going with this? Well.. in .NET4, Microsoft introduced collectible assemblies. These things allow you to define a dynamic assembly at runtime using reflection emit. So technically I can load and unload an assembly in the same app domain! Exactly what I want. Quick and easy. Whats the catch? Oh yeah.. Microsoft forgot to put in a LoadFromAssemblyFile function. This means if I already have compiled code, say from a WPF plugin that someone made (.dll file), I have no way of loading it in the dynamic assembly I just created. How to solve this issue? I have looked at many many things, and they are either impossible to do because the CLR is not open source, or they are just too time consuming. I would be an old fool by the time I got something working. Well.. I didnt just decide to post this message here intending to say "its impossible". The third option is:

    Writing an assembly CLR PE loader. I am currently undertaking the task of writing such a loader that will parse a pure IL CLR .dll assembly file. The loader will parse namespaces, classes, fields, etc. and load them into the dynamic assembly. Once the dynamic assembly is loaded, it can be used just like any other dynamic assembly that is loaded at runtime. Wouldn't it be awesome if you could write the following code?:

    using System;
    using System.Awesome;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace Program
    {
     public class AppStart
     {
     public static void Main(string[] args)
     {
     int result = 0;
    
     // Load dynamic assembly from filename TestAssembly.dll
     // in same directory as this application.
     DynamicAssembly assembly = DynamicAssembly.Load("TestAssembly");
    
     // Call a static function in the assembly.
     // This function is a static function that adds two numbers
     // and returns the result.
     result = (int)assembly.Execute("Test.TestClass.AddTwoNumbers", new object[] { 42, 77 });
    
     // Print out the result and the current assemblies
     // in this application domain
     Console.WriteLine(result);
     PrintAssemblies();
    
     // Let us now UNLOAD the assembly
     DynamicAssembly.Unload(assembly);
     Console.WriteLine("\n\n");
    
     // Print out the new list of assemblies in the
     // application domain
     PrintAssemblies();
     }
    
     private static void PrintAssemblies()
     {
     Assembly[] assms = AppDomain.CurrentDomain.GetAssemblies();
    
     foreach (Assembly a in assms)
     {
     Console.WriteLine(a.GetName().Name);
     }
     }
     }
    }
    

    Here's a screen of that code running.http://postimage.org/image/vho0yu04/. Of course... as of right now, the add function is "virtually implemented". That code is not loaded from the assembly file. Additionally, "Dynamic Assembly" in the list refers to the running application exe, which is named Dynamic Assembly. This is simply a unit test. I'm not done with the PE loader. Anyhow... I believe that it should be and is possible to do something of this nature. Again, this would support PURE .NET IL assemblies. I'll be damned if I am going to dabble in mixed or native assemblies. So... I would like to hear people's CONSTRUCTIVE thoughts on this subject. If you plan on attacking me outright for whatever reason.. (I have had that experience more than once, because I post so little), do not bother posting. I realize that it will take time and effort to perfect.

     LostTime77






    Hi;

    I am not quite following this - you need to help me - we can already load assemblies from files on disk or streams in memory - so can you explain what it you're trying to do that cannot be done already?

    Thx

    Cap'n

    Saturday, June 9, 2012 4:24 PM
  • LostTime77,

    What you do is the right approach (at this moment) to unload assemblies in AppDomains. If you can finish project like that, it might be useful to other people. CLR test team created similar test tool to dynamically RefEmit assembly based on something existing on the disk, so you should be able to do the same.

    Couple of notes:

    1. Watch out for restrictions in Collectible Assemblies - e.g. PInvoke, COM interop, thread statics, etc. - http://msdn.microsoft.com/en-us/library/dd554932(v=vs.100).aspx.
    2. Assembly.Load* APIs for Collectible Assemblies were not forgotten. They are just more expensive to implement. So we decided to start with the easier part (RefEmit) with some restrictions (that people hate as well and ask us "why?").
      Future versions of .NET will likely see improvements and lifted restrictions in this area. It just depends on how useful and expensive will be such features when compared to other features in CLR.

    BTW: You might find useful/reusable code in IKVM.NET (http://weblog.ikvm.net/). I know Jeroen played with Collectible Assemblies, so he most likely created similar tool like this.

    -Karel

    Tuesday, June 12, 2012 4:45 AM
    Moderator
  • LostTime77,

    Any luck with that? I havent found a clean enough solution myself yet.

    Tuesday, July 8, 2014 9:05 PM