在.Net Core(.Net6)中的程序集解析之前,静态构造函数不再运行



我正在将巨大的32位桌面(winforms)代码库从.NetFramework462迁移到.Net6。当从VisualStudio运行时,代码本身在迁移后运行良好。我们有大约150个csprojs,其中一些dll在多个可执行文件中共享,因此在安装过程中,我们将共享程序集放在C:ProgramFiles (x86)MyProgramAssemblies中,而不是将每个程序集复制到每个程序的子文件夹中。

我们有自定义的MyAssemblyLoader,如果应用程序根文件夹中缺少程序集,它可以正确地从Assemblies文件夹加载程序集。我们在程序的静态构造函数中注册我们的程序集加载器来处理AssemblyResolve事件,如下所示:

static class Program
{
private static MyAssemblyResolver _assemblyResolver = new MyAssemblyResolver();
static Program()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => _assemblyResolver.AssemblyResolve(args.Name);
}

// Main() and other code is here
}

问题是,当我在.NetFramework462下构建程序并从binDebug文件夹中删除一个依赖dll时,它会正确地从Assemblies文件夹中加载它。我可以在静态构造函数中设置一个断点,并查看它是否被调用。在.Net 6中的相同场景中,我甚至在运行静态构造函数之前就得到了System.IO.FileNotFoundException: 'Could not load file or assembly'。异常没有堆栈跟踪,也根本不进入静态构造函数,就像异常在调用之前就被抛出一样。

我试图加载一些其他程序集,这些程序集对于项目从Assemblies文件夹和即时窗口中的.Net6中的MyAssembliesLoader运行是不必要的,它运行得很好。

以下是关于如何在csprojs中引用它的详细信息(我认为这对运行时解析器来说并不重要):在.Net6中,我有SDK csprojs,通过一个共享项目引用了缺失的dll(dll在csproj中没有直接引用)

<ProjectReference Include="OneOfSharedProjects.csproj" />

和在OneOfSharedProjects.csproj

<ProjectReference Include="MissingDLL.csproj" />

在.NetFramework462中,该项目直接引用

<ProjectReference Include="MissingDLL.csproj">
<Project>{12345678-FFBC-419B-AEAB-3A9B1A4D4847}</Project>
<Name>MissingDLL</Name>
</ProjectReference>

Assemblies文件夹路径是在运行时解析的,所以我希望避免在配置文件中硬编码路径。如何从.Net 6中的自定义文件夹加载引用的库?

PS:

  • 我们的库没有在GAC中注册,所以情况并非如此
  • AssemblyResolve赋值从静态构造函数移到Main()没有帮助。代码的行为与以前一样(调用Main()之前的异常)

好的,我发现了问题。看起来问题是直接引用了Main()方法中缺少库的类。让我们假设类C在丢失的库中。有这样的主要:

class Program
{
static Program()
{
AppDomain.CurrentDomain.AssemblyResolve += (s, e) => _assemblyResolver.AssemblyResolve(e.Name);
}
static void Main()
{    
C c = new C();
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}

将不起作用,因为在添加程序集解析器作为事件处理程序之前,.Net6尝试加载包含C定义的库。但如果不直接使用缺失库中的类,问题就消失了。示例:

class Program
{
static Program()
{
AppDomain.CurrentDomain.AssemblyResolve += (s, e) => _assemblyResolver.AssemblyResolve(e.Name);
}
static void Main()
{
NewMethod();
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
private static void NewMethod()
{
C c = new C();
}
}

现在,即使dll被移动到AssemblyResolver可以找到它的其他地方,代码也会很好地工作

相关内容

  • 没有找到相关文章

最新更新