1

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

2
  • Put a breakpoint and inspect the contents of raw.DefinedTypes vs raw2.DefinedTypes. Are they comparable (same items, etc) ? Commented Sep 10, 2019 at 12:55
  • Yes, they are the same. It seems that the problem is located at 'Assembly Load(AssemblyName name)', when it return null; it works fine but when the LoadFromAssemblyPath is in it, it will stop working. Commented Sep 10, 2019 at 14:13

2 Answers 2

2

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 :)

Sign up to request clarification or add additional context in comments.

2 Comments

what please update with path examples
I have been struggling to get something working spent many many hours gone through countless resources and can not seem to get mine to work. Suggestions? mine is quite complex, but its so confusing as to what needs to be what. Plz help if you can
0

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).

1 Comment

Yeah, the problem seemed to be caused by mainAssemblyToLoadPath; I've used the wrong data there. I was wondering what is your reason to add a extension instead of making that in the class (or using the default logic). You're right about the loading in the constructor; at that time I wanted to re-use a certain code but at the same time testing (mostly playing with plugin like system at the moment)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.