简体   繁体   English

AssemblyLoadContext,动态加载程序集,实例化 object 并转换为共享接口

[英]AssemblyLoadContext, dynamically load an assembly, instantiate an object and cast to a shared interface

I'm trying to load an assembly with the AssemblyLoadContext (exists from the version 3.0 of netcore), instantiate an object and cast this object to an interface, but I get a cast exception error.我正在尝试使用AssemblyLoadContext加载程序集(从 netcore 版本 3.0 开始),实例化 object 并将此 object 转换为接口,但出现转换异常错误。

The interface is shared between the project that loads the assembly and the implementation instantiated.该接口在加载程序集的项目和实例化的实现之间共享。 The object apparently is instantiated correctly but I get the unexpected error when I do (T)instance . object 显然已正确实例化,但是当我执行(T)instance时出现意外错误。

Trying with watcher I'm able to cast the instance correctly to the interface, following the code I'm using and a screenshot of the watcher:尝试使用观察者,我能够按照我正在使用的代码和观察者的屏幕截图将实例正确地投射到界面:

private (ExecutionAssemblyLoadContext, T) LoadTheAssemblyAndInstance<T>(string assemblyName, string typeNameToInstance)
{
    var basePath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    var assemblyContext = new ExecutionAssemblyLoadContext($"{basePath}/{assemblyName}.dll");
    var assembly = assemblyContext.LoadFromAssemblyPath($"{basePath}/{assemblyName}.dll");
    var externalCodeEvent = typeNameToInstance != null ? assembly.ExportedTypes
        .Where(x => x.FullName == typeNameToInstance)
        .Single() : assembly.ExportedTypes.First();
    var instance = Activator.CreateInstance(
            externalCodeEvent,
            _defaultConstructorParameters
        );
    return (assemblyContext, (T)instance);
}

在此处输入图像描述

this is the full exception message:这是完整的异常消息:

System.InvalidCastException: 'Unable to cast object of type 'Expriva.NewWorkflow.BPMN.ExecutionCodeTest.ExecutionContractTest' to type 'Expriva.NewWorkflow.ExternalShared.Interfaces.IExecutionContract'.' System.InvalidCastException:“无法将“Expriva.NewWorkflow.BPMN.ExecutionCodeTest.ExecutionContractTest”类型的 object 转换为“Expriva.NewWorkflow.ExternalShared.Interfaces.IExecutionContract”。

Following a screenshot that shows that T is implemented by the instance下面的截图显示T是由实例实现的在此处输入图像描述

AssemblyLoadContext to support dynamic code loading and unloading, it creates an isolated context for loading code and its dependencies in their own AssemblyLoadContext instance. AssemblyLoadContext 支持动态代码加载和卸载,它在自己的 AssemblyLoadContext 实例中创建用于加载代码及其依赖项的隔离上下文。

The problem was that in the ExecutionAssemblyLoadContext implementation, the dependencies was resolved and isolated.问题是在 ExecutionAssemblyLoadContext 实现中,依赖关系被解决和隔离。 Using the default implementation, siggested by the documentation of AssemblyLoadContext the shared types will not be isolated.使用默认实现,AssemblyLoadContext 的文档表明共享类型不会被隔离。 Following the correct implementation to use to share the interface.按照正确的实现来使用共享接口。

public class ExecutionAssemblyLoadContext : AssemblyLoadContext
{
    public ExecutionAssemblyLoadContext() : base(isCollectible: true)
    {
    }

    protected override Assembly Load(AssemblyName name)
    {
        return null;
    }
}

I also came across this problem, think of it as if the different AssemblyLoadContext have their own copies of loaded types, so although you may reference the shared assembly in both contexts as far as they are concerned the types contained are unique.我也遇到过这个问题,可以把它想象成不同的 AssemblyLoadContext 有自己的加载类型的副本,因此尽管您可以在两个上下文中引用共享程序集,但就它们而言,所包含的类型是唯一的。

The solution is to use the Load override in the derived ALC to resolve the assembly from the shared context.解决方案是使用派生 ALC 中的 Load 覆盖从共享上下文中解析程序集。

This is simple if the shared types are loaded into the default ALC, for example.例如,如果将共享类型加载到默认 ALC 中,这很简单。

public class ModAssemblyLoadContext : AssemblyLoadContext
{
    public ModAssemblyLoadContext()
        : base("ModAssemblyLoadContext", isCollectible: true)
    {
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        return Default.Assemblies
            .FirstOrDefault(x => x.FullName == assemblyName.FullName);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM