Saturday, 20 September 2014

AppDomain and Dynamic Assemblies

I have been working on an application where there was a requirement to compile and create dynamic assembly. But since there was a lot of request has to be processed various/multiple requests for code compilation on the fly and generating assembly has to be entertain. I realized that generated assemblies remained in the memory which was a problem and could have result in out of memory issues if placed in the production.

Note: The Roslyn libraries are being used for the compilation for generating assemblies.

Requirement statement:

Compile the code at run time and load the generated assembly to run some tests against the generated assembly.

As I mentioned in introductory part, the assemblies were not unloading once the work was finished. Ofcourse the assemblies loaded in the AppDomain were only gets unloaded once the Appdomain is unloaded. Then I thought of understand the AppDomain rather just placing a plumbing code for the problem and so I came to wrote this blog.

AppDomain - The Definition stated by MSDN:

Application domains provide an isolation boundary for security, reliability, and versioning, and for unloading assemblies. Application domains are typically created by runtime hosts, which are responsible for bootstrapping the common language runtime before an application is run.

One thing that can be noted here is,

You must load the assembly in appdomain before executing it’s methods.

Perform the operation for execution of the logic in separate AppDomain.

Unload the assembly.

Note: If you’re creating an AppDomain with in a method then once the AppDomain is created it will be loaded over the CurrentApplication domain and the local variable defined or initialized in parent domain won’t be accessible to the new AppDomain.

But this problem can be solved by using the MarshalByRef. The MashalByRef is being used to make the objects of a class available across the boundary of the AppDomains. So in my case I had to mark the shared classes between the parent and child AppDomain as MashalByRef for sharing. One more important thing the class must be marked with Serializable.

How to create a custom Domain?

Below is the snippet to create an AppDomain with full security permission for local machine.

How to find currently loaded domains?

To check if your custom AppDomain is created, In Visual studio add a breakpoint in your application, Go to menu Debug -> Windows -> Modules.

clip_image002[4]

As shown in the above picture, there are three different AppDomain are loaded in the Module. The one with the GUID as name is my custom domain I created as ofcourse it’s an service hosted in IISExpress.

You can have question right now in mind, how can I get to know which domain is my current domain?

Answer, Trace.WriteLine(AppDomain.CurrentDomain.FriendlyName);

That’s it. It will show the currently loaded domain in the application.

What’s next?

Now, I had my custom domain loaded. To execute the desire method or logic I would need to get access to the assembly and invoke the method via reflection.(Though it will have some considerable performance issues).

Sample code:

That’s it once the job is finished I can unload the domain using following code.

That’s it. It solved my problem and ofcourse I get to know the benefits of Application Isolations in AppDomain.

But there are some things that can be considered into account. Any exception occurred in the custom appdomain will not be propagated to the parent appdomain. As a solution you can create a custom exception and mark it as Serializable as shown in this thread.