【问题标题】:How to use CSharpScript with 'globals' type from a DLL which is dynamically loaded into custom collectible AssemblyLoadContext如何从动态加载到自定义可收集 AssemblyLoadContext 的 DLL 中使用具有“全局”类型的 CSharpScript
【发布时间】:2020-06-13 02:05:21
【问题描述】:

脚本评估代码sn-p:

        using (var loader = new InteractiveAssemblyLoader())
        {
            var script = CSharpScript.Create<TDataType>(
           code: expr,
           options: ScriptOptions.Default.AddImports(globals.GetType().Namespace)
                                         .AddReferences(refAssemblies),
           globalsType: globals.GetType(),
           assemblyLoader: loader);

            return script.RunAsync(globals).Result.ReturnValue;
        }

代码分析程序集和全局类型程序集被加载到同一个 Collectible AssemblyLoadContext... 还尝试通过 ScriptOptions 显式添加引用/导入,但得到相同的以下错误:

内部异常 1: InvalidCastException:[A]TestLibrary.TestClass 无法转换为 [B]TestLibrary.TestClass。类型 A 源自 'TestLibrary,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null',位于位置 '...\TestLibrary.dll' 的上下文 'Default' 中。类型 B 源自 'TestLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 在上下文 'Default' 的位置 '...\TestLibrary.dll'。

【问题讨论】:

    标签: c# roslyn csharpscript


    【解决方案1】:

    似乎程序集加载器在您的动态代码中加载了两次TestLibrary,您可以避免手动解析程序集(注意两个项目中的 TestLibrary 必须是相同的版本)

    //Somewhere in your startup code:
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
    
    static Assembly MyResolveEventHandler(object sender, AssemblyLoadEventArgs args)         
    {
        //First time it will be null and the resolver will load it from the default path, the succesive requests to load the library will return the already loaded assembly.
        if(args.Name == "TestLibrary")
            return AppDomain.CurrentDomain.GetAssemblies().Where(a => a.Name == args.Name).FirstOrDefault(); 
    
        return null;
    }
    

    【讨论】:

    • FirstOrDefault 可以带谓词:AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a =&gt; a.Name == args.Name)
    • 在我的情况下,同一个程序集被加载到 2 个不同的加载上下文中...但是感谢您的解决方案...也许我可以调整它以检查自定义加载上下文并防止加载dll 再次进入默认加载上下文...
    • 这不起作用,因为在我的情况下没有触发 AssemblyResolve 事件,可能是因为系统解决了它并将程序集加载到默认加载上下文中......
    • @m3 如果您使用AssemblyLoadContext 加载库,那么您可以挂钩到上下文的Resolving 事件并执行与我的示例相同的操作,在域程序集中返回一个.
    • 只有在加载失败时才会触发解析,但在这种情况下加载到“默认”上下文中会成功,但我们希望阻止该加载,因为程序集已经加载到另一个上下文中...
    猜你喜欢
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2021-08-11
    • 2017-07-20
    • 1970-01-01
    • 2017-11-25
    相关资源
    最近更新 更多