3

我已经掌握了一个星期的 MEF,我正在尝试构建一个 WPF 应用程序,该应用程序可以从 MEF 加载导入的控件。

我创建了一个 WPF 应用程序项目并删除了默认窗口和应用程序启动 URI。然后我处理了应用程序启动事件来编写应用程序:

public partial class App : Application, IPartImportsSatisfiedNotification
{
    {...}

    private void App_Startup(object sender, StartupEventArgs e)
    {
        this.Compose();
    }

    public void Compose()
    {
        try
        {
            globalCatalog.Catalogs.Add(new DirectoryCatalog(extensionsDirectoryPath));
            CompositionContainer container = new CompositionContainer(globalCatalog);
            container.ComposeParts(this);
        }
        catch (Exception ex)
        {
            // Do something
        }
    }

    {...}
}

实际上,当满足导入后调试和观察对象时,一切都像我想要的那样分层组成。但是,当我尝试显示应用程序的 MainWindow 时,MainWindow.Show() 调用会引发异常:

“指定元素已经是另一个元素的逻辑子元素。先断开它。”

虽然我在 OnImportsSatisfied 方法中的代码看起来很好,因为它在不使用 MEF 机制时可以正常工作:

public void OnImportsSatisfied()
{
    Window mainWindow = new Window();
    mainWindow.Content = this.importedControl;
    this.MainWindow = mainWindow;
    this.MainWindow.Show();
}

我坚持这样一个事实,即当不使用 MEF 导入控件时,它可以完美地工作。令人惊讶的是,这段代码也不起作用:

Window mainWindow = new Window();
//mainWindow.Content = this.importedControl;
this.MainWindow = mainWindow;
this.MainWindow.Show();

所以我怀疑 ComposeParts 做的比它说的要多一些,因为它是唯一作用于我的实际应用程序实例的成员。

希望有人可以帮助我(格伦?)。谢谢。


编辑:

我发现当我从我的部件中删除 IPartImportsSatisfiedNotification 接口时,不会引发异常并且会显示窗口。但是当然窗口是空的,因为我需要这个 OnImportsSatisfied 方法将窗口的 DataContext 设置为其关联的导入视图模型。

4

2 回答 2

1

WPF 应用程序框架 (WAF)的示例应用程序展示了如何在 WPF 应用程序中使用 MEF。

于 2010-07-30T18:51:15.313 回答
0

我终于发现我正在使用默认的 ImportAttribute 构造函数导入我的 WPF 用户控件,如果在导出期间未指定创建策略,它实际上将创建类的共享实例。由于我的许多控件都实现了相同的界面并且我将它们绑定到我的视图中,因此我实际上试图将此共享的用户控件实例添加到不同的可视元素,这是 WPF 不允许的(因此例外)。

我使用设置为 NonShared 的 RequiredCreationPolicy 标记了我的导入,一切都恢复正常了!这就是学习MEF的全部内容......

于 2010-07-16T13:28:42.583 回答