c# – IoC未在Win7XP上初始化

c# – IoC未在Win7XP上初始化,第1张

概述我试图在Win7 / XP上运行 WPF应用程序时遇到一个非常奇怪的问题. WPF应用程序面向.NET 4.0,它引用了Caliburn.Micro 1.5.2和Autofac 3.1.0. 我将从问题摘要开始,然后我将详细介绍我到目前为止所得到的内容. 概述 在我的开发工作站中,我有Windows 8和Visual Studio 2012.我正在使用Caliburn和Autofac,如this 我试图在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:\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,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:\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中所见.但是,在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()
> 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()方法的代码没有,我给你详细解释了原因.

@H_404_116@ 总结

以上是内存溢出为你收集整理的c# – IoC未在Win7 / XP上初始化全部内容,希望文章能够帮你解决c# – IoC未在Win7 / XP上初始化所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1230043.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存