0

我正在尝试为 Prism 创建一个 LightInject 引导程序,我复制了NinjectBootstrapper( source ) 的代码并将 Ninject 替换IKernel为 LightInject IServiceContainer。我还创建并注册了一个LightInjectServiceLocatorAdapterNinject 版本)。

注册和服务定位器适配器正在工作。我看到该类RegionAdapterMappings已从服务定位器中成功检索。

在引导程序的步骤中,从服务定位器请求ConfigureRegionAdapterMappings一个类的实例。SelectorRegionAdapter这失败了。该课程从未注册过。我在NinjectBootstrapper. 那么 Ninject 引导程序是如何检索这个类的呢?

我已经尝试手动注册该类(以及更多的区域适配器和DelayedRegionCreationBehavior),但随后 Prism 失败并出现UpdateRegionsException

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Prism.Regions.Behaviors.RegionCreationException: An exception occurred while creating a region with name 'Menu'. The exception was: System.Collections.Generic.KeyNotFoundException: The IRegionAdapter for the type System.Windows.Controls.ContentControl is not registered in the region adapter mappings. You can register an IRegionAdapter for this control by overriding the ConfigureRegionAdapterMappings method in the bootstrapper.

我找不到任何处理创建添加自己的 DI 容器的来源,我不知道我错过了哪一步。我究竟做错了什么?

ServiceContainer像这样配置我的(Ninject 等价的ConfigureKernel方法)。

protected virtual void ConfigureServiceContainer()
{
    this.ServiceContainer.RegisterInstance<IServiceContainer>(this.ServiceContainer);
    this.ServiceContainer.RegisterInstance(this.Logger);
    this.ServiceContainer.RegisterInstance(this.ModuleCatalog);

    if (!this.useDefaultConfiguration)
        return;

    this.ServiceContainer.Register<IServiceLocator, LightInjectServiceLocatorAdapter>();
    this.ServiceContainer.Register<IModuleInitializer, ModuleInitializer>();
    this.ServiceContainer.Register<IModuleManager, ModuleManager>();

    this.ServiceContainer.Register<RegionAdapterMappings, RegionAdapterMappings>();

    // The following 4 registrations are not in the NinjectBootstrapper
    this.ServiceContainer.Register<SelectorRegionAdapter, SelectorRegionAdapter>();
    this.ServiceContainer.Register<ItemsControlRegionAdapter, ItemsControlRegionAdapter>();
    this.ServiceContainer.Register<ContentControlRegionAdapter, ContentControlRegionAdapter>();
    this.ServiceContainer.Register<DelayedRegionCreationBehavior, DelayedRegionCreationBehavior>();

    this.ServiceContainer.Register<IRegionManager, RegionManager>();
    this.ServiceContainer.Register<IEventAggregator, EventAggregator>();
    this.ServiceContainer.Register<IRegionViewRegistry, RegionViewRegistry>();
    this.ServiceContainer.Register<IRegionBehaviorFactory, RegionBehaviorFactory>();
    this.ServiceContainer.Register<IRegionNavigationJournalEntry, RegionNavigationJournalEntry>();
    this.ServiceContainer.Register<IRegionNavigationJournal, RegionNavigationJournal>();
    this.ServiceContainer.Register<IRegionNavigationService, RegionNavigationService>();
    this.ServiceContainer.Register<IRegionNavigationContentLoader, RegionNavigationContentLoader>();
}
4

1 回答 1

0

原来有两件事我做错了。

对于ConfigureServiceContainerNinject 引导程序中的注册,使用了一种扩展方法public static void RegisterTypeIfMissing<A, B>(this IServiceContainer container, bool singletonScope),该方法在单例范围内注册了一些依赖项。

我不明白的另一件事是,即使没有注册,Ninject 也会很乐意解析任何具体类型。LightInject 没有。我最终通过将 Prism.WPF 中以“行为”或“适配器”结尾的所有具体类注册到自己来解决这个问题,如下所示:

// Register all concrete adapters and behaviors in the Prism.WPF assembly
var wpfAssembly = typeof (SelectorRegionAdapter).Assembly;
this.ServiceContainer.RegisterAssembly(wpfAssembly, (t0, t1) => t0.Name.EndsWith("Adapter") || t0.Name.EndsWith("Behavior"));

最后我不得不放弃 Prism 的所有模块管理。LightInject 期望一个扩展自的类ICompositionRoot出现在程序集中,并从那里愉快地加载类型。这对我的方法很好:)。

于 2017-06-18T21:47:47.227 回答