c# – IoC未在Win7 / XP上初始化
我试图在Win7 / XP上运行
WPF应用程序时遇到一个非常奇怪的问题. WPF应用程序面向.NET 4.0,它引用了Caliburn.Micro 1.5.2和Autofac 3.1.0.
我将从问题摘要开始,然后我将详细介绍我到目前为止所得到的内容. 概述 在我的开发工作站中,我有Windows 8和Visual Studio 2012.我正在使用Caliburn和Autofac,如this post所述(基本上是this的简化版本). 当我在我的开发机器中构建并运行应用程序时,一切都按预期进行.但是,当我获取二进制文件并在Windows 7 / XP机器中执行它时,我得到以下错误,带有长堆栈跟踪: System.InvalidOperationException: IoC is not initialized 我可以在环境(除OS之外)看到的唯一区别是我的开发工作站有.NET 4.5,而Win7 / XP有.NET 4.0. 细节 我能用一个简单的应用程序重现这个问题.解决方案: ShellViewModel只是一个空导体< Screen>. ShellView只有一个TextBlock. App.xaml遵循Caliburn的推荐: <Application x:Class="WpfApplication2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication2"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary> <local:Bootstrapper x:Key="bootstrapper" /> </ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application> App.xaml.cs代码已修改为捕获并显示异常: public partial class App : Application { public App () { // hook on error before app really starts AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); try { this.InitializeComponent(); } catch (Exception e) { MessageBox.Show(e.ToString()); throw; } } public static void CurrentDomain_UnhandledException(object sender,UnhandledExceptionEventArgs e) { MessageBox.Show(((Exception)e.ExceptionObject).ToString()); } } 有趣的部分是Bootstrapper.如上所述,我有一个应用程序,并与Caliburn和Autofac一起运行,与一个类似于此处描述的Bootstrapper一起工作.例如,我创建了一个简化版本: public class Bootstrapper : Bootstrapper<ShellViewModel> { private IContainer container; protected IContainer Container { get { return this.container; } } protected override object GetInstance(Type serviceType,string key) { if (string.IsNullOrWhiteSpace(key)) { if (container.IsRegistered(serviceType)) return container.Resolve(serviceType); } else { if (container.IsRegisteredWithName(key,serviceType)) container.ResolveNamed(key,serviceType); } throw new Exception(string.Format("Could not locate any instances of contract {0}.",key ?? serviceType.Name)); } protected override IEnumerable<object> GetAllInstances(Type serviceType) { return this.Container.Resolve(typeof(IEnumerable<>).MakeGenericType(serviceType)) as IEnumerable<object>; } protected override void BuildUp(object instance) { this.Container.InjectProperties(instance); } protected override void Configure() { var builder = new ContainerBuilder(); builder.RegisterType<ShellViewModel>(); builder.RegisterAssemblyTypes(this.GetType().Assembly); builder.RegisterType<WindowManager>() .As<IWindowManager>() .SingleInstance(); builder.RegisterType<EventAggregator>() .As<IEventAggregator>() .SingleInstance(); this.container = builder.Build(); } } 在我的工作站中,它运行得很好: 我在Bootstrapper的GetInstance方法中加入了一些断点,它们被正确命中. 然后,我拿了二进制文件(bin / Debug)并尝试在Windows XP / 7虚拟机中运行它们.该应用程序无法启动,我得到以下异常: System.InvalidOperationException: IoC is not initialized. at Caliburn.Micro.IoC.<.cctor>b__0(Type service,String key) in c:UsersRobDocumentsCodePlexcaliburnmicrosrcCaliburn.Micro.SilverlightIoC.cs:line 13 at Caliburn.Micro.IoC.Get[T](String key) in c:UsersRobDocumentsCodePlexcaliburnmicrosrcCaliburn.Micro.SilverlightIoC.cs:line 32 at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor(Type viewModelType,IDictionary`2 settings) in c:UsersRobDocumentsCodePlexcaliburnmicrosrcCaliburn.Micro.SilverlightBootstrapper.cs:line 254 at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor[TViewModel](IDictionary`2 settings) in c:UsersRobDocumentsCodePlexcaliburnmicrosrcCaliburn.Micro.SilverlightBootstrapper.cs:line 264 at Caliburn.Micro.Bootstrapper`1.OnStartup(Object sender,StartupEventArgs e) in c:UsersRobDocumentsCodePlexcaliburnmicrosrcCaliburn.Micro.SilverlightBootstrapper.cs:line 288 at System.Windows.Application.OnStartup(StartupEventArgs e) at System.Windows.Application.<.ctor>b__1(Object unused) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback,Object args,Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source,Delegate method,Int32 numArgs,Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code,CleanupCode backoutCode,Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback callback,Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state,Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext,Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd,Int32 msg,IntPtr wParam,IntPtr lParam,Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd,Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback,Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority,TimeSpan timeout,Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd,IntPtr lParam) at MS.Win32.UnsafeNativeMethods.MessageBox(HandleRef hWnd,String text,String caption,Int32 type) at System.Windows.MessageBox.ShowCore(IntPtr owner,String messageBoxText,MessageBoxButton button,MessageBoxImage icon,MessageBoxResult defaultResult,MessageBoxOptions options) at System.Windows.MessageBox.Show(String messageBoxText) at WpfApplication2.App..ctor() in c:UsersPublicProjetosOutrosWpfApplication3WpfApplication2App.xaml.cs:line 27 at WpfApplication2.App.Main() in c:UsersPublicProjetosOutrosWpfApplication3WpfApplication2objDebugApp.g.cs:line 0 该消息显然是在初始化之前调用IoC类时的预期行为,如我们在Caliburn’s source中所见.但是,在Bootstrapper调用Configure之后,IoC正确初始化.请参阅the source中的BootstrapperBase.StartRuntime方法. 如果我从Bootstrapper中删除所有依赖注入逻辑,该应用程序在Win XP / 7上运行正常. 我花了一些时间试图找到究竟是什么触发了这种行为.我从Bootstrapper中删除了所有内容,经过一些尝试,以下是触发问题所需的全部内容: public class Bootstrapper : Bootstrapper<ShellViewModel> { protected override void Configure() { var builder = new ContainerBuilder(); builder.RegisterType<ShellViewModel>(); } } 如果我注释行builder.RegisterType< ShellViewModel>();,该应用程序可以正常工作. 结论:在Autofac ContainerBuilder中注册任何内容的简单操作会触发行为.我甚至不需要使用它.我对此完全感到困惑. 我花了好几个小时来解决这个问题.我真的很想使用Caliburn和Autofac,因为我喜欢它们.如果有人能说清楚它,我会很感激. UPDATE 我注意到如果我在Bootstrapper.Configure方法中调用MessageBox.Show,即使在我的Win8中使用VS2012进行调试,也会发生观察到的行为(“IoC未初始化”): public class Bootstrapper : Bootstrapper<ShellViewModel> { protected override void Configure() { MessageBox.Show("Configure"); } } 我正在考虑它,但我还不知道它意味着什么. UPDATE Link for the sample application. UPDATE 在分析观察到的行为之后,我得出结论(正如Sniffer所做的那样)“IoC未初始化”错误的原因不是依赖注入,而是在Bootstrapper启动之前调用MessageBox.Show. 我将MessageBox.Show更改为NLog的日志记录例程,将错误写入文件,然后我就能找到真正的异常.真正的问题来自于Autofac针对PCL以及它与.NET 4.0 Client Profile一起运行的事实,我需要install the update 4.0.3 in target machine. 然而,抛开原来的问题,Caliburn实际上存在问题.在Bootstrapper初始化之前调用MessageBox.Show似乎会触发在IoC配置之间发生的全新Application启动过程,从而生成观察到的异常. 我认为目前的问题偏离了原来的目的,我认为它应该是封闭的.我将在不受特定应用程序问题影响的环境中创建一个针对Caliburn.Micro问题的新问题. 解决方法
好吧,我在我的XP机器上运行你的代码并且你的上次更新有问题,你使用MessageBox类的那个,它导致你的Windows 8机器上出现问题,但是前面的代码,你创建一个新容器并注册你说的ShellViewModel在你的win 7 / xp机器上引起了问题并没有给我带来任何问题(编译并运行正常).
现在我想知道为什么在Configure方法中使用MessageBox.Show()方法导致该异常,我想出了原因,并归结为: > Caliburn.Micro(后来的CM)Bootstrapper< TRootModel>构造函数调用Start() 简介:具有容器配置的代码在我的Win XP机器上没有问题,但配置()覆盖中的MessageBox.Show()方法的代码没有,我给你详细解释了原因. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |