Efficiently loading assemblies at runtime with .NET 6*

14 March 2024

Back in the days of .NET framework, it was straightforward to load assemblies at runtime using the ‘System.Reflection’ library alone. However, when platform agnostic .NET Core was introduced, it came with a lot of modern designs that broke conventional implementations. Loading runtime assemblies was one of them.

I spent a good amount of time figuring out a generic way of achieving this and developed a reusable & simple open-source library. This library is tested and works on .NET 6 and onward.

.net blog
.net blog
What this library does?

Loading assemblies is an important part of many programs. In most cases, your static dependencies will be loaded automatically, but dynamic dependencies require the active use of various assembly loader APIs. This library provides a ready-to-use single API that can resolve both managed and unmanaged dependencies of an application.

Why to use this library?

DynamicDependencyLoader library allows you to develop and deploy pluggable solutions easily and efficiently without any 3rd party (free or paid) dependencies.

Library location: https://github.com/dheerajawale-svg/dynamic-dependency-loader

Nuget package: https://www.nuget.org/packages/DynamicDependencyLoader

How to use?

Here is what you do when you have a main application in which you want to dynamically load another assembly/plugin.

  • Add the 'DynamicDependencyLoader' library to your main application project.
  • Get the path of the assembly/plugin you want to load at runtime.
  • Call  RuntimeAssemblyLoader.CreateFromAssemblyFile(assembly_Path) function and pass the path to it.
  • Now when you want to use this assembly just call LoadDefaultAssembly() at the point of invocation.

Then use the below function and pass application settings to it.

.net blog
picture2
High level functioning of the library
  • The main application project will reference 'DynamicDependencyLoader' library.
  • After the application starts, a user must decide if the plugin assembly should be loaded and determine the path of the assembly.
  • The application then tells RuntimeAssemblyLoader class of DynamicDependencyLoader to load the assembly from the given file path.
  • Plugin assembly is now part of the main application, and its features are available to the main application. 
How it works

The library makes use of ‘System.Reflection’ and ‘System.Runtime.Loader’ DLLs to accomplish the dynamic loading of assemblies.

Below are the purposes for using the mentioned components:

System.Reflection

Purpose:

  • The classes in the System.Reflection namespace provide a managed view of loaded assemblies and the types defined within them (such as classes, interfaces, and value types).
  • You can use reflection to obtain information about these elements dynamically.
  • For example, you can retrieve details about a class, its constructors, and its methods.
SYSTEM.RUNTIME.LOADER

Purpose:

  • The classes in System.Runtime.Loader allows you to load assemblies independently by reading *.deps.json, isolate them, and unload them when no longer needed.
  • It also helps in loading different versions of the same assembly if needed.
ABOUT SYSTEM.RUNTIME.LOADER

System.Runtime.Loader reference is the heart of this library. Hence, let us explore it below.

System.Runtime.Loader exposes AssemblyLoadContext class that helps implementing dynamic loading.

WHAT IS THE ASSEMBLYLOADCONTEXT?

Every .NET Core and .NET 5+ application implicitly uses AssemblyLoadContext. It is the runtime's provider for locating and loading dependencies. Whenever a dependency is loaded, an AssemblyLoadContext instance is invoked to locate it.

  • AssemblyLoadContext provides a service for locating, loading, and caching managed assemblies and other dependencies.
  • To support dynamic code loading and unloading, it creates an isolated context for loading code and its dependencies in its AssemblyLoadContext instance.

You can find the step-by-step official algorithm of how this class works here.

Further technical details could be part of a future blog in the same series. But for a major population, this level of detail should suffice to decide on the usage of the library.

KEY TAKEAWAYS
  • With modern design, Binding redirects do not apply to .NET Core or .NET 5+ applications.
  • When assemblies cannot be loaded in a traditional way, System.Runtime.Loader provides a bunch of methods that are used to resolve assemblies at runtime.
  • With the help of the 'DynamicDependencyLoader' library, you can dynamically load/resolve assemblies with only a couple of lines of code.
auther.net

This blog is written by Dheeraj Awale, Associate Software Architect at Decos. He is expert in Full-stack development as well as Windows development which includes technologies like Angular, React, Blazor, Azure, DotNet Core, WPF etc. and comes with wealth of experience in medical device software development.
Decos is a cutting-edge technology services partner ready to meet your diverse needs across various industries, including the medical domain. If you have a question on one of our projects or would like advice on your project or a POC,  contact Devesh Agarwal. We’d love to get in touch with you!

Send an email

Discover more

portable medical device
Role of Human Factors Engineering in Design of Portable Medical Devices
Introduction Portable medical devices are essential in contemporary healthcare, designed to be used in various environments, whether indoors or outdoors. These devices can vary in...
Read more
Application containerization
Deploying Applications with Ease: A Guide to Containerization
What are Containers? Applications that run in isolated runtime environments are called containerised applications. Containers encapsulate an application with all its dependencies, including system libraries...
Read more
medical device usability
A User-Focused Approach to Medical Device Development: Identifying Usability Challenges and Prioritizing Solutions
Introduction Users play a crucial role in the user-interface development process. They contribute at different stages of device development. User involvement during the initial stages...
Read more