解决.NET 5中的Prism WPF中模块的间接依赖性
我们最近将我们的Prism应用程序从.NET Framework 4.7迁移到.NET5。我们最初使用Prism 4(没有.NET 5兼容目标)观察到了这个问题,但我们也与Prism 8一起看到了这一点
。该应用程序的设置是此
- 模块 - > EventsLib
- Moduleb-> Eventlib
- 应用程序(配置模块A和B)
我们使用XML文件来定义要加载的模块组件和类型名称,然后将此信息传递为moduleinfo
实例,将其传递给模块目录。所有二进制文件都在同一文件夹中。
对于.NET Framework 4.7不需要其他代码来确保还加载了间接参考(EventLib),并可以从Modulea和Moduleb解决类型。
对于.net 5,这不再起作用:我在尝试启动应用程序时会得到ModuletyPeloAdernotFoundException
。这发生在prism.modularity.modulemanager.getTypeloAderformodule
方法中。从挖掘到棱镜来源,我认为这是因为type.getType()(在某个点为模块类型的某个点调用)不再加载依赖项,除非它们已经在应用程序的deps.json中列出(这使模块化概念完全崩溃了)。
我可以通过为应用程序的.NET 5目标添加以下内容来解决此问题:
- 作为我们自定义目录的初始化的一部分,我设置了一个用于汇编事件的处理程序:
#if NET5_0_OR_GREATER
System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += OnResolving;
#endif
- 在此处理程序中,我尝试从本地目录(以及用于资源的其他处理)
private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName)
{
if (this.failedAssemblies.Contains(assemblyName.Name))
{
return null;
}
if (assemblyName.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
return this.LoadResourceAssembly(loadContext, assemblyName);
}
string assemblyRootPath = System.AppDomain.CurrentDomain.BaseDirectory;
var assemblyPath = System.IO.Path.Join(assemblyRootPath, assemblyName.Name) + ".dll";
var assembly = this.LoadAssemblyFromPath(loadContext, assemblyPath);
if (assembly == null)
{
this.failedAssemblies.Add(assemblyName.Name);
}
return assembly;
}
我的(也许是天真的)假设是,有了Prism版本(支持.NET 5目标),这不再需要。
我的问题是:这不是必要的,我们需要配置某些内容以启用某些内置的组装分辨率机制,或者现在始终需要在自定义模块目录中处理汇编分辨率,以适用于以.NET 5(或以后运行) )应用?
We have recently migrated our Prism application from .NET Framework 4.7 to .NET 5. We observed this issue initially with Prism 4 (which doesn't have a .NET 5 compatible target) but we also see this with Prism 8.
To simplify the situation the setup of the application is this
- ModuleA -> EventsLib
- ModuleB -> EventsLib
- Application (configures Modules A and B)
We are using an XML file to define the module assembly and type names to be loaded and pass this information packaged as a ModuleInfo
instance to the module catalog. All binaries are in the same folder.
For .NET Framework 4.7 no additional code was necessary to ensure that the indirect reference (EventLib) was also loaded and types could be resolved from ModuleA and ModuleB.
For .NET 5 this doesn't work anymore: I get a ModuleTypeLoaderNotFoundException
when trying to launch the application. This occurs in the Prism.Modularity.ModuleManager.GetTypeLoaderForModule
method. From digging a bit into Prism sources I think this due to the fact that Type.GetType() (which is called at some point for the module types) no longer loads dependencies unless they are already listed in the deps.json of the application (which makes the modularity concept completely fall apart). This post and its comment helped me understand the differences in assembly loading for .NET Framework and .NET Core/.NET 5/6.
I can resolve this problem by adding the following for the .NET 5 target of our application:
- as part of the initialization of our custom catalog I set up a handler for assembly resolve events:
#if NET5_0_OR_GREATER
System.Runtime.Loader.AssemblyLoadContext.Default.Resolving += OnResolving;
#endif
- in this handler I try to load the requested assembly from the local directory (with additional handling for resources)
private Assembly OnResolving(AssemblyLoadContext loadContext, AssemblyName assemblyName)
{
if (this.failedAssemblies.Contains(assemblyName.Name))
{
return null;
}
if (assemblyName.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
{
return this.LoadResourceAssembly(loadContext, assemblyName);
}
string assemblyRootPath = System.AppDomain.CurrentDomain.BaseDirectory;
var assemblyPath = System.IO.Path.Join(assemblyRootPath, assemblyName.Name) + ".dll";
var assembly = this.LoadAssemblyFromPath(loadContext, assemblyPath);
if (assembly == null)
{
this.failedAssemblies.Add(assemblyName.Name);
}
return assembly;
}
My (maybe naive) assumption was that with version 8 of Prism (which supports .NET 5 targets) this should no longer be necessary.
My question: isn't it necessary and we need to configure something to enable some built-in assembly resolution mechanism or is it now always necessary to handle assembly resolution in the custom module catalog for Prism applications that run as .NET 5 (or later) applications?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论