/// private" /> /// private" /> /// private"/>

How to get interface from object loaded from AssemblyLoadContext

55 Views Asked by At
/// <summary>
/// Here asm is loaded from HostAssemblyLoadContext 
/// </summary>
/// <param name="asm"></param>
/// <param name="alc"></param>
private void OptimizerAction(Assembly asm, HostAssemblyLoadContext alc)
{
    var types = asm.GetTypes().Where(type => type.GetInterface(nameof(IOptimizer)) != null).ToList();
    if (types.Count != 1)
    {
        return;
    }

    Type typeIOptimizer = types[0];
    MethodInfo? getInstance = typeIOptimizer.GetMethod("GetInstance", BindingFlags.Static | BindingFlags.Public);
    if (getInstance != null)
    {
        object? obj = getInstance.Invoke(null, null);
        if (obj != null)
        {
            Debug.Assert(obj.GetType().Name == "Optimizer");
            var iopt = obj as IOptimizer;
            Debug.Assert(iopt != null); // ASSERTION FAIL *******

            if (obj is IOptimizer opt) // NEVER TRUE *******
            {
                opt.Optimize();   // HERE Never called. Thers is no IOptimizer found when loaded from AssemblyLoadContext
            }
        }
    }

Code loaded with AssemblyLoadContext give different behavior (than not using it):

In code, the assertion should be true. It is the case when not using AssemblyLoadContext.

     var iopt = obj as IOptimizer;
     Debug.Assert(iopt != null); // ASSERTION FAIL *******

In code, the next line should also be true. It is the case when not using AssemblyLoadContext.

  if (obj is IOptimizer opt) // NEVER TRUE *******

How to get the same behavior as when not using AssemblyLoadContext?

I know this question is the same as this: AssemblyLoadContext, dynamically load an assembly, instantiate an object and cast to a shared interface. I know it seems to have different types (IOptimizer) seems to be 2 different types. But how to deal with that? Is there a way to be the same because they both comes from the same DLL? It should be the same.

Reference:

public class Optimizer : IOptimizer
{
    public static IOptimizer GetInstance() { return new Optimizer(); }
    ...

Code available at GitHub - EricOuellet2/AssemblyLoadContext

1

There are 1 best solutions below

0
Eric Ouellet On

I found the solution to my problem. I found the solution in the Microsoft code sample at line 24 of this .cs file: Github AssemblyLoadcontext Microsoft sample. (It is the same code which I started my sample but I haven't read everything).

I was referencing twice the same "OptimizerInterface.dll" where my interfaces were defined. One dll was in my main app folder and the other copy was in the folder where the dynamic loaded dll was. I removed the copy of "OptimizerInterface.dll" from the folder where the dynamic dll was loaded. BOOM -> Problem solved!!!

You can find the message (warning) in provided code in Github. You can also try the solution with the same code. Ref: Sample code to reproduce the error