如何从AssemblyLoadContext加载的对象获取接口

问题描述 投票:0回答:1
/// <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
            }
        }
    }

代码可在:Github - EricOuellet2/AssemblyLoadContext

使用 AssemblyLoadContext 加载的代码会产生不同的行为(与不使用它相比):

在代码中,断言应该为真。不使用 AssemblyLoadContext 时就是这种情况。

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

在代码中,下一行也应该为 true。不使用 AssemblyLoadContext 时就是这种情况。

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

如何获得与不使用 AssemblyLoadContext 时相同的行为???

我知道:这个问题与此相同:AssemblyLoadContext,动态加载程序集,实例化对象并转换为共享接口。我知道它似乎有不同的类型(IOptimizer)似乎是两种不同的类型。但如何处理呢?有没有办法做到相同,因为它们都来自同一个 dll。应该是一样的。

但是我需要一个答案,我会为此提供赏金(如果有的话)。

参考:

public class Optimizer : IOptimizer
{
    public static IOptimizer GetInstance() { return new Optimizer(); }
    ...
c# reflection casting dynamic-loading assemblyloadcontext
1个回答
0
投票

我找到了解决问题的方法。我在 .cs 文件第 24 行的 Microsoft 代码示例中找到了解决方案:Github AssemblyLoadcontext Microsoft 示例。 (这与我开始示例的代码相同,但我还没有阅读所有内容)。

我两次引用了定义接口的 dll。 On dll 位于我的主应用程序文件夹中,另一个副本位于动态加载的 dll 所在的文件夹中。我从加载动态 dll 的文件夹中删除了已定义接口的 dll 副本。繁荣 -> 问题解决了!!!

您可以在 Github 中提供的代码中找到该消息(警告)。您也可以使用相同的代码尝试解决方案。参考:重现错误的示例代码

© www.soinside.com 2019 - 2024. All rights reserved.