加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 21:53:21 所属栏目:百科 来源:网络整理
导读:我试图在Win7 / XP上运行 WPF应用程序时遇到一个非常奇怪的问题. WPF应用程序面向.NET 4.0,它引用了Caliburn.Micro 1.5.2和Autofac 3.1.0. 我将从问题摘要开始,然后我将详细介绍我到目前为止所得到的内容. 概述 在我的开发工作站中,我有Windows 8和Visual St
我试图在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()
> 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()方法的代码没有,我给你详细解释了原因.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读