Sitemap
Vikas Jindal

Vikas Jindal

I am student, learning and want to learn a lot. By profession, Works in Software Industry - Developer and Time Reader - Astrologer.

AssemblyLoadContext in C#

3 min readJan 19, 2025

--

The AssemblyLoadContext class in .NET Core and later is a mechanism for loading and managing assemblies at runtime. It provides a way to control the loading and unloading of assemblies, offering flexibility for scenarios like plugins, dynamic loading, and isolation.

1. What is AssemblyLoadContext?

  • It is the .NET Core equivalent of AppDomains in .NET Framework, but it focuses specifically on assembly loading and unloading.
  • Each AssemblyLoadContext acts as an isolated context for managing assemblies and their dependencies.

2. Why Use AssemblyLoadContext?

a. Plugin Development

Load plugins dynamically without impacting the main application or other plugins.

b. Assembly Unloading

Unload assemblies to reclaim memory and resources when they are no longer needed.

c. Dependency Isolation

Load different versions of an assembly or conflicting dependencies in separate contexts.

d. Testing and Scripting

Load assemblies dynamically during testing or executing user-provided scripts.

3. Key Features of AssemblyLoadContext

a. Default vs. Custom Contexts

  • Default Context: The default loading context for the application, typically used for loading the application’s main assemblies.
  • Custom Context: Allows for creating isolated contexts for loading assemblies independently.

b. Unloading

Custom contexts can unload assemblies using garbage collection when no references remain.

c. Assembly Resolution

Customizable resolution logic for locating and loading assemblies.

4. Creating and Using AssemblyLoadContext

Example 1: Loading an Assembly Dynamically

Here’s a basic example of loading an assembly dynamically using a custom AssemblyLoadContext:

using System;
using System.Reflection;
using System.Runtime.Loader;

class CustomLoadContext : AssemblyLoadContext
{
protected override Assembly Load(AssemblyName assemblyName)
{
// Custom logic to resolve the assembly
Console.WriteLine($"Loading assembly: {assemblyName.FullName}");
return null; // Return null to use the default resolution.
}
}
class Program
{
static void Main()
{
var context = new CustomLoadContext();
// Load an assembly from a file
Assembly assembly = context.LoadFromAssemblyPath(@"C:\path\to\your\assembly.dll");
// Access types and members of the assembly
Type type = assembly.GetType("Namespace.ClassName");
MethodInfo method = type.GetMethod("MethodName");
method.Invoke(null, null);
// Unloading the context
context.Unload();
Console.WriteLine("Assembly unloaded.");
}
}

5. Assembly Unloading

Assemblies loaded in a custom AssemblyLoadContext can be unloaded when:

  1. All references to the AssemblyLoadContext and its loaded assemblies are released.
  2. The garbage collector collects the AssemblyLoadContext.

Get Vikas Jindal’s stories in your inbox

Join Medium for free to get updates from this writer.

Example: Unloading an Assembly

using System;
using System.Reflection;
using System.Runtime.Loader;

class Program
{
static void Main()
{
WeakReference contextReference = LoadAndUnloadAssembly();
// Force garbage collection to unload the context
for (int i = 0; i < 10 && contextReference.IsAlive; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine(contextReference.IsAlive ? "Context is still alive" : "Context has been unloaded");
}
static WeakReference LoadAndUnloadAssembly()
{
var context = new AssemblyLoadContext("CustomContext", isCollectible: true);
Assembly assembly = context.LoadFromAssemblyPath(@"C:\path\to\your\assembly.dll");
// Create a WeakReference to the context for monitoring unloading
var weakReference = new WeakReference(context);
// Unload the context
context.Unload();
return weakReference;
}
}

6. Assembly Resolution in AssemblyLoadContext

Custom Resolution Logic

You can override the Load method to define custom assembly resolution logic.

Example: Resolving Dependencies

using System;
using System.IO;
using System.Reflection;
using System.Runtime.Loader;

class CustomLoadContext : AssemblyLoadContext
{
private string _dependencyPath;
public CustomLoadContext(string dependencyPath)
{
_dependencyPath = dependencyPath;
}
protected override Assembly Load(AssemblyName assemblyName)
{
string assemblyPath = Path.Combine(_dependencyPath, assemblyName.Name + ".dll");
if (File.Exists(assemblyPath))
{
return LoadFromAssemblyPath(assemblyPath);
}
return null; // Use default resolution if not found
}
}
class Program
{
static void Main()
{
var context = new CustomLoadContext(@"C:\path\to\dependencies");
Assembly assembly = context.LoadFromAssemblyName(new AssemblyName("DependencyName"));
Console.WriteLine($"Loaded assembly: {assembly.FullName}");
}
}

7. Best Practices

  1. Use isCollectible: true for Unloading:
  • Set isCollectible to true when creating the context to enable unloading.

2. Monitor Dependencies:

  • Ensure that no references to assemblies in the context remain to allow for proper unloading.

3. Handle Exceptions:

  • Handle scenarios where assemblies cannot be resolved.

4. Avoid Overloading the Default Context:

  • Use custom contexts for loading assemblies dynamically to prevent polluting the default context.

8. Limitations

  1. Cannot Unload Default Context:
  • Only custom contexts support unloading.

2. Requires Careful Dependency Management:

  • Circular dependencies or missing references can cause runtime issues.

3. Garbage Collection Dependency:

  • Assembly unloading is tied to garbage collection, so it’s not immediate.

9. Practical Scenarios for AssemblyLoadContext

  1. Plugin Systems:
  • Load plugins dynamically and unload them when no longer needed.

2. Runtime Updates:

  • Dynamically load updated assemblies without restarting the application.

3. Testing Environments:

  • Load test assemblies in isolation to avoid conflicts.

4. Script Execution:

  • Execute user-provided scripts with isolated dependencies.

--

--

Written by Vikas Jindal

I am student, learning and want to learn a lot. By profession, Works in Software Industry - Developer and Time Reader - Astrologer.