在Shell中获取IModuleManager的实例

时间:2013-03-12 15:10:21

标签: wpf prism mef

我一直在尝试使用PRISM和MEF编写WPF应用程序,并且我已经能够启动并运行Shell。我希望能够按需加载模块,因此我需要在Shell中使用IModuleManager的实例。但是,当我尝试导入它时,应用程序会中断。以下是相关代码:

引导程序:

public class Bootstrapper : MefBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return this.Container.GetExportedValue<Shell>();
    }

    protected override void InitializeShell()
    {
        base.InitializeShell();

        Application.Current.MainWindow = (Shell)this.Shell;
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureAggregateCatalog()
    {
        base.ConfigureAggregateCatalog();

        // Add this assembly to export ModuleTracker
        this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

        DirectoryModuleCatalog moduleCatalog = new DirectoryModuleCatalog();
        moduleCatalog.ModulePath = @".\Modules";
        moduleCatalog.Load();
        foreach (ModuleInfo moduleInfo in moduleCatalog.Modules)
        {
            this.ModuleCatalog.AddModule(moduleInfo);
        }

        DirectoryCatalog catalog = new DirectoryCatalog(@".\Modules");
        this.AggregateCatalog.Catalogs.Add(catalog);

        base.ConfigureAggregateCatalog();
    }

    protected override void ConfigureContainer()
    {
        //Export the Container so that it can be injected if needed.
        this.Container.ComposeExportedValue(Container);

        //Export the Module Catalog so that it can be injected if needed.
        this.Container.ComposeExportedValue(ModuleCatalog);

        base.ConfigureContainer();
    }

    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ConfigurationModuleCatalog();
    }
}

外壳:

[Export(typeof(Shell))]
public partial class Shell : Window, IPartImportsSatisfiedNotification
{
    [Import(AllowRecomposition = false)]
    private IModuleManager moduleManager;

    public Shell()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {

    }

    public void OnImportsSatisfied()
    {

    }
}

我得到的例外是:

No exports were found that match the constraint: 
ContractName    Shell
RequiredTypeIdentity    Shell

如果我删除了IModuleManager的[Import]属性,一切正常。导出IModuleManager需要做些什么吗?

2 个答案:

答案 0 :(得分:0)

通过在Bootstrapper中注释以下行来解决此问题:

this.Container.ComposeExportedValue(ModuleCatalog);

不确定为什么会导致问题,但欢迎任何有关此问题的见解。

答案 1 :(得分:0)

您必须注意的一件事是同一类型的多个导出。当您使用ComposeExportedValue以及使用DirectoryCatalog(可能包含相同类型的Export)时,很容易发生这种情况。

Nuget有一个很棒的软件包来诊断这些问题MEFX

如果你有这个库,你可以添加以下行来帮助找出正在发生的事情

var compositionInfo = new CompositionInfo(AggregateCatalog, Container);
CompositionInfoTextFormatter.Write(compositionInfo, Console.Out);

如果您不介意发布任何错误,我会很高兴看到当您在程序中保留this.Container.ComposeExportedValue(ModuleCatalog);时打印到“输出”窗口的内容。