gpt4 book ai didi

c# - 在Win7/XP上未初始化IoC

转载 作者:行者123 更新时间:2023-11-30 12:47:10 25 4
gpt4 key购买 nike

尝试在Win7 / XP上运行WPF应用程序时,我遇到了一个非常奇怪的问题。 WPF应用程序以.NET 4.0为目标,它引用了Caliburn.Micro 1.5.2和Autofac 3.1.0。

我将从问题的总结开始,然后再提供到目前为止的详细信息。

总览

在我的开发工作站中,我有Windows 8和Visual Studio2012。我正在使用Caliburn和Autofac,如this post中所述(基本上是this的简化版本)。

当我在开发机中构建并运行应用程序时,一切都会按预期进行。但是,当我使用二进制文件并在Windows 7 / XP计算机上执行它们时,出现以下错误,并且堆栈跟踪很长:

System.InvalidOperationException: IoC is not initialized


我可以看到的两种环境之间的唯一区别(除操作系统之外)是我的开发工作站具有.NET 4.5,而Win7 / XP的工作站具有.NET 4.0。

细节

我能够通过一个简单的应用程序重现该问题。解决方案:



ShellViewModel只是一个空的 Conductor<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相似,与所描述的 here类似。对于示例,我创建了一个简化版本:

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();
}
}


在我的工作站上,它运行得很好:



我在 BootstrapperGetInstance方法中添加了一些断点,它们已被正确命中。

然后,我获取了二进制文件(bin / Debug),并尝试在Windows XP / 7虚拟机中运行它们。该应用程序无法启动,并且出现以下异常:

System.InvalidOperationException: IoC is not initialized.

at Caliburn.Micro.IoC.<.cctor>b__0(Type service, String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 13

at Caliburn.Micro.IoC.Get[T](String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 32

at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor(Type viewModelType, IDictionary`2 settings) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 254

at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor[TViewModel](IDictionary`2 settings) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 264

at Caliburn.Micro.Bootstrapper`1.OnStartup(Object sender, StartupEventArgs e) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.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, Object args, 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, ContextCallback callback, Object state, Boolean ignoreSyncCtx)

at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, 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, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)

at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)

at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

at MS.Win32.UnsafeNativeMethods.MessageBox(HandleRef hWnd, String text, String caption, Int32 type)

at System.Windows.MessageBox.ShowCore(IntPtr owner, String messageBoxText, String caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options)

at System.Windows.MessageBox.Show(String messageBoxText)

at WpfApplication2.App..ctor() in c:\Users\Public\Projetos\Outros\WpfApplication3\WpfApplication2\App.xaml.cs:line 27

at WpfApplication2.App.Main() in c:\Users\Public\Projetos\Outros\WpfApplication3\WpfApplication2\obj\Debug\App.g.cs:line 0


该消息显然是初始化之前调用 IoC类时的预期行为,正如我们在 Caliburn's source中看到的那样。但是, IoCBootstrapper调用 Configure之后立即正确初始化。请参见 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,因为我俩都喜欢。如果有人能对此有所了解,我将不胜感激。

更新

我注意到,如果我在Bootstrapper.Configure方法中调用MessageBox.Show,即使在Win8中使用VS2012进行调试,也会发生观察到的行为(“未初始化IoC”):

public class Bootstrapper : Bootstrapper<ShellViewModel>
{
protected override void Configure()
{
MessageBox.Show("Configure");
}
}


我正在考虑,但是我还不知道这意味着什么。

更新

Link for the sample application.

更新

在分析观察到的行为之后,我得出结论(如Sniffer所做的那样),即“未初始化IoC”错误的原因不是依赖项注入,而是在 MessageBox.Show启动之前调用 Bootstrapper

我将 MessageBox.Show更改为NLog的日志记录例程,以将错误写入文件,从而可以跟踪真正的异常。真正的问题来自Autofac瞄准PCL,并且要使其能够在.NET 4.0 Client Profile中正常运行,我需要 install the update 4.0.3 in target machine

但是,撇开原始问题,实际上Caliburn存在问题。在引导程序初始化之前,调用MessageBox.Show似乎会触发一个新的应用程序启动过程,该过程在IoC配置之间发生,从而生成观察到的异常。

我认为当前问题已经偏离了其最初的目的,我认为应该将其结束。我将在不受我的特定应用程序问题影响的环境中创建一个针对Caliburn.Micro问题的新问题。

最佳答案

好吧,我在XP机器上运行了您的代码,并在上次更新时遇到了问题,该问题是您使用MessageBox类的,它在Windows 8机器上导致了您的问题,但是上一个代码是您在其中创建新容器的,注册您在Win 7 / xp机器上引起问题的ShellViewModel并没有引起我任何问题(它编译并运行正常)。

现在我想知道为什么在MessageBox.Show()方法中使用Configure方法会导致该异常,而我却想出了原因,并且可以归结为:


Caliburn.Micro的(在此后为CM)Bootstrapper<TRootModel>构造函数正在调用Start()
Start()正在呼叫StartRuntime()
StartRuntime()正在按此特定顺序进行呼叫:Configure()然后IoC.Get = GetInstance然后IoC.GetAllInstances = GetAllInstances;然后IoC.BuildUp = BuildUp;
StartRuntime()调用Configure()时,将执行您的代码,特别是MessageBox.Show(),这是一项系统功能,要求(必须)每个消息框都具有一个所有者窗口,并且默认情况下,所有者是您当前的活动应用程序窗口。
现在在此阶段运行了一段系统代码,我不知道正在运行什么,但是由系统执行的那段代码调用了OnStartup()方法覆盖,CM在引导程序中覆盖了该覆盖并使用它来显示您选择的TRootModel的视图。
为了使Caliburn显示该TRootModel的视图,它需要一个IWindowManager实例,并使其使用(您已弄清楚)我们所钟爱的IoC(如您在第3步中看到的那样),它没有尚未初始化,它仍然停留在该Configure()方法上,并且没有继续进行。


摘要:具有容器配置的代码在我的Win XP计算机上可以正常工作,但是在MessageBox.Show()覆盖中使用Configure()方法的代码没有问题,我为您提供了详细的原因说明。

关于c# - 在Win7/XP上未初始化IoC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17622546/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com