如何使用 DryIoc 而不是 Unity 在 Prism 中配置模块目录?

How do I Configure the Module Catalog in Prism using DryIoc instead of Unity?

我正在使用 Prism 库 WPF 示例 here (specifically, this one).

我正在尝试将示例的引导程序从使用 Unity 容器转换为 DryIoc。原始代码如下所示:

class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureModuleCatalog()
    {
        var catalog = (ModuleCatalog)ModuleCatalog;
        catalog.AddModule(typeof(ModuleAModule));
    }
}

我的新代码如下所示:

class Bootstrapper : DryIocBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        return Container.Resolve(typeof(MainWindow), true) as DependencyObject;
    }

    protected override void InitializeShell()
    {
        Application.Current.MainWindow.Show();
    }

    protected override void ConfigureModuleCatalog()
    {
        var catalog = (ModuleCatalog)ModuleCatalog;
        catalog.AddModule(typeof(ModuleAModule));
    }
}

但是当我尝试 运行 新代码时,出现以下异常:

内部异常说:

Activation error occurred while trying to get instance of type ModuleAModule, key ""

那个异常的内部异常说:

Unable to get constructor of DryIoc.Rules using provided constructor selector when resolving DryIoc.Rules {ReturnDefault} as parameter "rules"
  in DryIoc.Container as parameter "container"
  in ModuleA.ModuleAModule.

ModuleAModule 的代码:

public class ModuleAModule : IModule
{
    IRegionManager _regionManager;
    Container _container;

    public ModuleAModule(RegionManager regionManager, Container container)
    {
        _regionManager = regionManager;
        _container = container;
    }

    public void Initialize()
    {
        _regionManager.RegisterViewWithRegion("ContentRegion", typeof(PersonList));

        _container.RegisterTypeForNavigation<PersonDetail>();
    }
}

而不是将具体的 Container 类型传递给模块构造函数 - 您需要传递 IContainer:

public ModuleAModule(RegionManager regionManager, IContainer container)
{
    _regionManager = regionManager;
    _container = container;
}

这将解决您的问题,但导航将不起作用。要修复导航 - 您需要对 RegionManager 执行相同的操作,即:传递 IRegionManager 而不是具体类型:

public ModuleAModule(IRegionManager regionManager, IContainer container)

不仅在模块本身,而且在其他地方,例如在PersonListViewModel:

public PersonListViewModel(IRegionManager regionManager)

传递具体实现通常不是一个好的做法,这里它在 DryIoc 的多个级别上中断。这是因为 ContainerRegionManager 作为具体类型都没有在 DryIoc 容器中注册(仅接口)。但是,当您尝试解析未注册的类型时,DryIoc 不会抛出异常,而是会尝试创建此类型的实例(并解析其依赖项(如果有))。

Container 中,创建失败。使用 RegionManager 它成功了,但问题是每个解决方案都会创建 RegionManager 的新实例(而 IRegionManager 接口被注册为单例)。所以你的模块,你的 PersonListViewModel 等都有不同的区域管理器实例,所以导航中断。