C#
.NET
assembly-loading
reflection
method-invocation

Correct Way to Load Assembly, Find Class and Call Run Method

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Loading an assembly at runtime and calling a Run() method is a common plugin pattern in .NET. The reliable solution is to separate two concerns: how the assembly is loaded and how the target type is discovered and invoked.

Prefer a Shared Contract Over Raw Reflection

If you control both sides of the system, define a shared interface in a small contract assembly. That removes most of the brittle string-based reflection logic.

csharp
1public interface IRunnable
2{
3    void Run();
4}

A plugin can implement that interface:

csharp
1public sealed class ReportJob : IRunnable
2{
3    public void Run()
4    {
5        Console.WriteLine("Report job is running.");
6    }
7}

Then the host loads the plugin assembly, finds the concrete type, creates it, and calls Run() through the interface:

csharp
1using System.Reflection;
2using System.Runtime.Loader;
3
4string assemblyPath = Path.GetFullPath(args[0]);
5Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
6
7Type? runnableType = assembly.GetTypes()
8    .FirstOrDefault(t =>
9        typeof(IRunnable).IsAssignableFrom(t) &&
10        !t.IsInterface &&
11        !t.IsAbstract);
12
13if (runnableType is null)
14{
15    throw new InvalidOperationException("No IRunnable implementation was found.");
16}
17
18var instance = (IRunnable?)Activator.CreateInstance(runnableType);
19if (instance is null)
20{
21    throw new InvalidOperationException($"Could not create {runnableType.FullName}.");
22}
23
24instance.Run();

This approach gives you compile-time checking for the method signature and avoids typos in class names or method names.

When You Must Use Reflection by Name

Sometimes you do not have a shared contract and must load a specific type by its full name. In that case, be explicit about the type name, constructor requirements, and method signature.

csharp
1using System.Reflection;
2using System.Runtime.Loader;
3
4string assemblyPath = Path.GetFullPath("Plugin.dll");
5Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
6
7Type type = assembly.GetType("PluginNamespace.JobRunner", throwOnError: true)!;
8object instance = Activator.CreateInstance(type)
9    ?? throw new InvalidOperationException("Could not create plugin instance.");
10
11MethodInfo runMethod = type.GetMethod(
12    "Run",
13    BindingFlags.Instance | BindingFlags.Public,
14    binder: null,
15    types: Type.EmptyTypes,
16    modifiers: null
17) ?? throw new MissingMethodException(type.FullName, "Run");
18
19runMethod.Invoke(instance, null);

The important part is the explicit method lookup. GetMethod("Run") by itself can return the wrong overload if multiple methods share that name.

Loading Dependencies Correctly

Loading the main assembly is often not the hard part. The real failure happens when the plugin has its own private dependencies in the same folder. In modern .NET, use a custom AssemblyLoadContext with AssemblyDependencyResolver when plugins need isolated dependency resolution.

csharp
1using System.Reflection;
2using System.Runtime.Loader;
3
4public sealed class PluginLoadContext : AssemblyLoadContext
5{
6    private readonly AssemblyDependencyResolver _resolver;
7
8    public PluginLoadContext(string pluginPath)
9    {
10        _resolver = new AssemblyDependencyResolver(pluginPath);
11    }
12
13    protected override Assembly? Load(AssemblyName assemblyName)
14    {
15        string? path = _resolver.ResolveAssemblyToPath(assemblyName);
16        return path is null ? null : LoadFromAssemblyPath(path);
17    }
18}

Usage:

csharp
string pluginPath = Path.GetFullPath("Plugin.dll");
var context = new PluginLoadContext(pluginPath);
Assembly assembly = context.LoadFromAssemblyPath(pluginPath);

If your plugin references packages that are not already loaded by the host, this extra step can be the difference between a working loader and a FileNotFoundException.

Choosing Between Assembly.Load and LoadFromAssemblyPath

Use the API that matches your input:

  • If you have an assembly name, Assembly.Load is appropriate.
  • If you have a file path, use LoadFromAssemblyPath.

Passing a file path into the wrong API is a common source of confusion. It can work differently than expected because .NET resolves names and paths through different mechanisms.

For plugin scenarios, a file-path-based load is usually the clearer and safer choice.

Make Failure Modes Obvious

Runtime loading code is much easier to debug when each failure has a specific message. Do not let everything collapse into a generic reflection exception.

Good loader code should fail clearly when:

  • the file path is wrong,
  • the type cannot be found,
  • the type is abstract or lacks a public constructor,
  • the Run() method is missing or has the wrong signature,
  • the plugin's dependencies cannot be resolved.

That makes support work dramatically easier once multiple plugins exist.

Common Pitfalls

  • Using Assembly.Load with a file path instead of a real assembly name.
  • Searching for a type by short name when the assembly contains more than one matching class.
  • Calling GetMethod("Run") without checking the parameter list or overloads.
  • Assuming plugin dependencies will resolve automatically without a custom load context.
  • Building a reflection-only design when a shared interface would remove most of the fragility.

Summary

  • The best design is a shared contract such as IRunnable plus runtime assembly loading.
  • If you must use reflection, look up the exact type and exact Run() signature.
  • 'LoadFromAssemblyPath is the right API when you are starting from a plugin file path.'
  • Plugin dependencies often require AssemblyDependencyResolver and a custom AssemblyLoadContext.
  • Clear error handling is essential because runtime loading failures are otherwise hard to diagnose.

Course illustration
Course illustration

All Rights Reserved.