Reputation: 31
I cannot seem to get a DefinedType based on a interface (IStartupPlugin), it seems to work with AssemblyLoadContext.Default.LoadFromAssemblyPath however when using my own class it doesn't :(
var raw = AssemblyLoadContext.Default.LoadFromAssemblyPath(pluginPath + Path.DirectorySeparatorChar + fqName + ".dll");
var raw2 = assemblyContext.LoadFromAssemblyPath(pluginPath + Path.DirectorySeparatorChar + fqName + ".dll");
bool hasDefined = raw.DefinedTypes
.Where(x => typeof(IStartupPlugin).IsAssignableFrom(x) && x != null && x != typeof(IStartupPlugin))
.Any();
bool hasDefined2 = raw2.DefinedTypes
.Where(x => typeof(IStartupPlugin).IsAssignableFrom(x) && x != null && x != typeof(IStartupPlugin))
.Any();
public class PluginAssemblyContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;
public PluginAssemblyContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
this.LoadFromAssemblyPath(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
hasDefined = true
hasDefined2 = false
Both of them is expected to have true as value hasDefined
and hasDefined2
Upvotes: 1
Views: 1323
Reputation: 31
It seems I have goofed with the creation of the assembly resolver! I used the path to the '.dll' file (mainAssemblyToLoadPath), however it seems like it asked for the path to the plugin directory (main directory), or so I guessed it seems to work fine now :)
Upvotes: 1
Reputation: 991
It's usually a bad practice to run such code within a constructor. Define a static (extension) method in a static class then load the desired assembly from anywhere in your app using an instance of your custom PluginAssemblyContext class. Concretely, try this:
public class PluginAssemblyContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;
public PluginAssemblyContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return LoadFromAssemblyPath(assemblyPath);
}
return null;
}
}
Define this class somewhere within a namespace with proper usings...
public static class PluginAssemblyContextExtensions
{
public static Assembly FromAssemblyPath(this AssemblyLoadContext context, string path)
{
return context.LoadFromAssemblyPath(path);
}
}
...from somewhere else (preferably within a static method/constructor), call the above code when your app has finished starting. I didn't have a chance to test this but I suspect the smell of your code comes from within the PluginAssemblyContext constructor you defined. Please let me know if I'm right (or wrong).
Upvotes: 0