【问题标题】:Prism and IEventAggregator: Trouble at loading ModulesPrism 和 IEventAggregator:加载模块时遇到问题
【发布时间】:2014-09-03 12:14:16
【问题描述】:

我实际上正在使用 WPF、MEF 和 Prism 开展一个项目。当我启动应用程序时,我需要从容器中导出一个模块以在显示主窗口之前打开一个配置窗口。因此代码是这样的:

        protected override void OnStartup(StartupEventArgs e)
        {       base.OnStartup(e);
                Bootstrapper bootstrapper = new Bootstrapper();
                bootstrapper.Run();

                var window = bootstrapper.statcontainer.GetExport<Configshell>();
                var configview = bootstrapper.statcontainer.GetExport<Module.Module1.View.ConfigView>();
                window.Value.Show();
                Keyboard.Focus(configview.Value.ok_button); }

其中 bootstrapper.statcontainer 是一个公共 CompositeContainer(在 CreateContainer-Method 中与 MEFBootstrapper 的“Maincontainer”一起分配)。我用它在启动时导出模块。 现在在 GetExport() 我得到以下第一次机会异常:

在先决条件导入 'MyApp.Module.Module2.ViewModels.Module2_Functions..ctor (Parameter="C_Aggregator", ContractName="Microsoft.Practices.Prism.PubSubEvents.IEventAggregator")' 设置之前无法调用 GetExportedValue。

这就是那里的 ctor 的样子:

    [Import]
    public IEventAggregator Configaggregator;

    [ImportingConstructor]
    public Module2_Functions(IEventAggregator C_Aggregator)
    {
        this.Configaggregator = C_Aggregator;
        Configaggregator.GetEvent<FromConfigWindow>();
        FromConfigWindow.Instance.Subscribe(receiveStatusFromConfigWindow);
        Configaggregator.GetEvent<ToConfigWindow>();
    }

我正在使用 EventAggregator 发布配置并在另一个模块中具有相同的 ctor。令人困惑的是,在我向该 ViewModel 添加另一个完全独立的导入之前,它一直是这样工作的。以下是 ConfigwindowViewModel 的 ctor 的样子:

    [ImportingConstructor]
    public ConfigVM(IEventAggregator C_aggregator)
    {
        this.Configaggregator = C_aggregator;
        Configaggregator.GetEvent<ToConfigWindow>();
        ToConfigWindow.Instance.Subscribe(actualizeCompStatus);
        Configaggregator.GetEvent<FromConfigWindow>();
    }

    [Import]
    public IEventAggregator Configaggregator;

这两个事件看起来像这样,并且都已经工作到 2 天前 ;-)

[Export]
public class FromConfigWindow : PubSubEvent<Int16> 
{
    private static readonly EventAggregator _eventAggregator;
    private static readonly FromConfigWindow _event;

    static FromConfigWindow()
    {
        _eventAggregator = new EventAggregator();
        _event = _eventAggregator.GetEvent<FromConfigWindow>();
    }

    public static FromConfigWindow Instance
    {
        get { return _event; }
    }
}
[Export]
public class ToConfigWindow : PubSubEvent<Int16>
{
    private static readonly EventAggregator _eventAggregator;
    private static readonly ToConfigWindow _event;

    static ToConfigWindow()
    {
        _eventAggregator = new EventAggregator();
        _event = _eventAggregator.GetEvent<ToConfigWindow>();
    }

    public static ToConfigWindow Instance
    {
        get { return _event; }
    }
}

所以最终问题在我看来就像 EventAggregator 没有被实例化,因此异常被抛出。但是我该如何解决这个问题?还是我在构造函数中聚合器的链接做错了什么?

我已经尝试使用 [Import] 属性修改所有构造函数参数,这也引发了相同的异常,或者从 ViewModel 中的 IEventAggregator Configaggregator 对象中删除了所有 [Import] 属性。

问题类似于this link here,但在我的例子中,发生在 Prism 框架中的 EventAggregator 上。

请告诉我是否应该为您提供更多代码部分。

【问题讨论】:

    标签: c# wpf prism mef bootstrapper


    【解决方案1】:

    我不确定您为什么要导出 PubSubEvents 或在其中保留对静态新 EventAggregator 的引用。您应该只使用一个从容器中获取的EventAggregator 实例(在本例中)(Prism 会为您放置它)。

    您应该回到基础并阅读出色的Prism documentation。第 9 节“松散耦合组件之间的通信”概述了 EventAggregator 和 PubSubEvents。

    如果您想创建一个简单的项目来模拟您遇到的问题并将其上传到某个地方,我很乐意为您看看。

    【讨论】:

    • 因为我是 Prism 的新手,所以我试着像一些人 herehere 那样做,但你是对的,我只是测试了它,不需要一些事件类本身的附加代码。我现在还通过使用 ServiceLocator 获得了 EventAggregator,效果很好:public IEventAggregator Configaggregator = ServiceLocator.Current.GetInstance&lt;IEventAggregator&gt;();感谢您的帮助!
    • 为什么直接从容器中获取EventAggregator而不是导入呢?
    【解决方案2】:

    看起来错误是因为您在开始操作之前没有满足所有导入。我同意 ChrisO,你应该回去查看文档。这里发生了很多事情,这些事情似乎过于复杂。为什么里面有new EventAggregator()? MEF 应该为您导入该依赖项。为什么要搞乱容器并获得出口?看来您正在做很多应该由 MEF 和 Prism 处理的工作。

    【讨论】:

    • 是的,因为这是我的第一个软件项目,而且我是 Prism 的新手,我一直意识到很多事情我做得过于复杂 ;-) 你是对的,容器可以更好地通过我现在发现的 ServiceLocator 方法:var container = ServiceLocator.Current.GetInstance(CompositionContainer); 到目前为止我还没有测试过,只是在 Miguel Bronzovic 的帖子中找到了here。感谢您的帮助!
    • 当然。但我真正想知道的是你为什么需要容器?它的工作就是在你需要的地方注入你需要的东西的实例。如果您尝试从容器中获取特定实例,请查看 MEF ExportFactory mef.codeplex.com/wikipage?title=PartCreator 而不是获取容器。我已经编写了大约 50 个基于 MEF 的应用程序,并且从不需要在组合时间之外直接访问容器。
    • 是的,但我将其作为一种解决方法,因为我需要在 App-Class 中注入 Import。在引导程序完成后,我的 Imports 一直为“null”(尽管 executionAssembly 被放置在 AggregateCatalog 中)并且出现了异常。所以我决定直接访问当时工作的容器。另一种可能性是使用配置窗口切换应用程序的主窗口,但我不喜欢这种方法,因为它会破坏架构的结构。
    猜你喜欢
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 2019-05-18
    • 2012-01-07
    • 1970-01-01
    相关资源
    最近更新 更多