I want to inspect assemblies if they have a specific type without loading the assembly in the current scope, which is available via MetadataLoadContext in .NET Core 3.
But if I try the following example
internal static class Program
{
// ReSharper disable once UnusedParameter.Local
private static void Main(string[] args)
{
var paths = new string[] { @"Plugin.dll" };
var resolver = new PathAssemblyResolver(paths);
var pluginInterface = typeof(IPlugin);
using (var context = new MetadataLoadContext(resolver))
{
var assembly =
context.LoadFromAssemblyName(@"Plugin");
foreach (var type in assembly.GetTypes())
{
if (type.IsClass && pluginInterface.IsAssignableFrom(type))
Console.WriteLine("found");
}
}
}
}
I get an exception
System.IO.FileNotFoundException: Could not find core assembly. Either specify a valid core assembly name in the MetadataLoadContext constructor or provide a MetadataAssemblyResolver that can load the core assembly.
at var context = new MetadataLoadContext(resolver)
What is meant by core assembly ? Or what I am doing wrong ? https://blog.vincentbitter.nl/net-core-3-0/ seems not working for me.
The existing answer didn't worked for me (.NET Core 2.1). It fails with error that System.Runtime is not found. If i hardcode full path to System.Runtime, it fails for other assemblies, like System.Private.CoreLib. Also checking types via IsAssignableFrom seems not working when one type isn't from MetadataLoadContext.
The possible solution for assembly load errors is to include all BCL assemblies (all .dll files in directory returned by RuntimeEnvironment.GetRuntimeDirectory). This feels somewhat dumb, because not all of them are actually managed assemblies, but it seems to work. Here's complete example of searching types that implement interface via MetadataLoadContext:
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
namespace MetadataLoadContextSample
{
class Program
{
static int Main(string[] args)
{
string inputFile = @"Plugin.dll";
string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");
var paths = new List<string>(runtimeAssemblies);
paths.Add(inputFile);
var resolver = new PathAssemblyResolver(paths);
var context = new MetadataLoadContext(resolver);
using (context)
{
Assembly assembly = context.LoadFromAssemblyPath(inputFile);
AssemblyName name = assembly.GetName();
foreach (TypeInfo t in assembly.GetTypes())
{
try
{
if (t.IsClass && t.GetInterface("IPlugin") != null)
{
Console.WriteLine(t.Name);
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("FileNotFoundException: " + ex.Message);
}
catch (TypeLoadException ex)
{
Console.WriteLine("TypeLoadException: " + ex.Message);
}
}
}
Console.ReadLine();
return 0;
}
}
}