首先,我们很清楚这不是一个严格意义上的Prism 6.3的问题;我们正在寻找的(如果一个解决方案不是直接的)是指向问题的解决方案的指针--顺便说一句--这就是: Windows 10 version 1903,通过.NET -thanks 4.8的包含,打破了我们原本功能完善,久经考验的,基于生产部署的Prism 6.3的商业软件。我们使用的是棱镜(核心)、Prism.WPF和Prism.MEF (都是6.3版本)。每当我们尝试实例化一个已注册的视图时,我们得到的(后面的源代码)是以下运行时错误:
Prism.Regions.RegionNavigationService.CreateNewRegionItem(String candidateTargetContract)抛出InvalidOperationException: Cannot create navigation target 'xyzView'. Activation error ocurred while tring to get instance of type Object, key 'xyzView'.
内部异常源于Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key),它抛出一个ActivationException: Activation error ocurred while tring to get instance of type Object, key 'xyzView'.
这里有一些相关的代码(xyzView = ExpedicionView或ExpedicionMaestroView,都会触发异常):
[ModuleExport(typeof(ExpedicionModulo))]
[Export(typeof(IMenu))]
public class ExpedicionModulo : IModule, IMenu
{
[Import]
public IRegionManager RegionManager;
[Import]
public ILoggerFacade Logger;
[ImportingConstructor]
public ExpedicionModulo(IRegionManager regionManager, ILoggerFacade logger)
{
Logger = logger;
RegionManager = regionManager;
// irrelevant (for our purposes) code omitted here
}
public void Initialize()
{
// Here's how we register views for main region
RegionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(ExpedicionView));
RegionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(MaestroExpedicionView));
// Some more registering for our dialog region
RegionManager.RegisterViewWithRegion(RegionNames.DialogRegion, typeof(ExpedicionDetalleView));
// other views registered in the very same fashion
Logger.Log("Expedition Module initialized", Category.Info, Priority.None);
}我们在下面这段代码中调用RequestNavigate:
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ShellViewModel : BaseViewModel
{
public IRibbonPrincipal RibbonPrincipal { get; set; }
private readonly InteractionRequest<Confirmation> _confirmationInteractionRequest;
private readonly InteractionRequest<Notification> _notificationInteractionRequest;
private string _seccionActiva;
private string _subseccionActiva;
private IRegionManager _regionManager;
[ImportingConstructor]
public ShellViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, ILoggerFacade logger)
: this(eventAggregator, logger)
{
try
{
_regionManager = regionManager;
_regionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(PrincipalView));
}
catch (Exception ex)
{
this.LoggerError(ex.Message);
}
}
public ShellViewModel(IEventAggregator eventAggregator, ILoggerFacade logger)
: base(eventAggregator, logger)
{
try
{
// Some irrelevant (to our purposes) initialization code omitted here
New = new DelegateCommand(() => { }, () => { return false; }); // etc.
_confirmationInteractionRequest = new InteractionRequest<Confirmation>();
_notificationInteractionRequest = new InteractionRequest<Notification>();
// Events code omitted for brevity sake
EventAggregator.GetEvent<MessageBoxEvent>().Subscribe(ShowMessageBox, ThreadOption.PublisherThread, false); // etc.
// View loading wireup
CambioSeccion = new DelegateCommand<object>(OnCambioSeccion);
CambioSubseccion = new DelegateCommand<object[]>(OnCambioSubseccion);
// some more irrelevant (to our purposes) code omitted here.
}
catch (Exception ex)
{
this.LoggerError(ex.Message);
}
}
/// <summary>
/// This is where we instantiate the View (WAI in .NET Framework <=4.7.2)
/// </summary>
/// <param name="objeto"></param>
private void OnCambioSeccion(object objeto)
{
// Ribbon menu handling here
RibbonPrincipal.ResetRibbon();
IIdentifyViewModel ivm = null;
// We are passing the View's name via clicked TreeViewItem in this case (param objeto)
TreeViewItem treeViewItem = (TreeViewItem)objeto;
if (treeViewItem != null && !string.IsNullOrEmpty(treeViewItem.Name))
{
_seccionActiva = treeViewItem.Name;
// Now we build the actual RequestNavigate invoke
// In our case, _seccionActiva would equal "Expedicion" or "MaestroExpedicion"
_regionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri("/" + _seccionActiva + "View", UriKind.Relative), (r) =>
{
if (!r.Result.HasValue || !r.Result.Value)
{
// error handling code here
}
else
{
ivm = ((FrameworkElement)_regionManager.Regions[RegionNames.MainContentRegion].ActiveViews.First()).DataContext as IIdentifyViewModel;
}
});
// Some event triggering here
if (ivm != null)
{
Seccion.Cambio(EventAggregator, ivm.ID);
}
}
}对于这篇长篇大论的帖子,很抱歉,并提前谢谢你。
发布于 2019-09-20 02:30:17
@mcandal感谢您的撰写。这看起来像是我们在模式和实践激活代码中看到的.NET Framework4.8中引入的最新问题。潜在的问题是,在4.8中,类型的构造函数以不同的顺序返回,导致模式和实践选择第一个(例如。ctors)有时不再正确。当我们在即将发布的版本中修复时,有一些变通方法。此问题仅影响ngen的程序集。解决办法: 1)禁用包含以下类型的程序集的ngen:
<configuration>
<runtime>
<disableNativeImageLoad>
<assemblyIdentity name="assembly_name" />
</disableNativeImageLoad>
</runtime>
</configuration>2)对于被激活的类型,只有1个ctor (模式和实践的文档假设只有1个ctor) 3)选择其他提供的激活模型,您可以在其中传递参数的类型,以避免歧义。
正如我所提到的,我们正在努力修复,如果你想进一步讨论,你可以提交一个VS反馈项目并链接到这篇文章,我们可以在那里继续讨论。
https://stackoverflow.com/questions/57868815
复制相似问题