/// <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(); }
...
我找到了解决问题的方法。我在 .cs 文件第 24 行的 Microsoft 代码示例中找到了解决方案:Github AssemblyLoadcontext Microsoft 示例。 (这与我开始示例的代码相同,但我还没有阅读所有内容)。
我两次引用了定义接口的 dll。 On dll 位于我的主应用程序文件夹中,另一个副本位于动态加载的 dll 所在的文件夹中。我从加载动态 dll 的文件夹中删除了已定义接口的 dll 副本。繁荣 -> 问题解决了!!!
您可以在 Github 中提供的代码中找到该消息(警告)。您也可以使用相同的代码尝试解决方案。参考:重现错误的示例代码