14 March 2024

Efficiently loading assemblies at runtime with .NET 6*

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

medical device label
Critical Role of Medical Device Labelling: Ensuring Safety, Compliance, and Patient Well-being
Medical devices play a vital role in diagnosing, treating, and monitoring various medical conditions, enhancing the quality of patient care, and improving outcomes. Yet, an...
Read more
Open AI
Exploring the Capabilities of OpenAI API
As technology continues to evolve, artificial intelligence (AI) has become an integral part of our lives. One of the most exciting and famous developments in...
Read more
FEA analysis
How FEA is Revolutionizing Material Science
Finite Element Analysis (FEA) is a numerical technique that breaks down large, complicated engineering issues into smaller, easier-to-manage components. Using mathematical models, the computer-based simulation...
Read more