c#-将单例注册为Prism 7接口的集合

由于不再支持MEF,因此我正在使用用于IOC的MEF将Prim 6转换为Prism 7 Unity.我必须解决的最大区别是,MEF中的假设是默认情况下所有内容都是单例的,而Unity则相反.

我已将大多数转换,但是我遇到的一件事是让构造函数通过集合引用单例.例如,我有以下接口和类:

public interface IAppService { }

public interface IDebugService : IAppService { }
public class DebugService : IDebugService { }

public interface IOtherService : IAppService { }
public class OtherService : IOtherService { }

使用DebugService和OtherService注册为单例并映射到它们各自的两个接口:

public void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterSingleton<IModuleMessageBus, ModuleMessageBus>();

    containerRegistry.RegisterSingleton<DebugService>();
    containerRegistry.RegisterSingleton<IDebugService, DebugService>();
    containerRegistry.Register<IAppService, DebugService>(typeof(DebugService).FullName);

    containerRegistry.RegisterSingleton<OtherService>();
    containerRegistry.RegisterSingleton<IOtherService, OtherService>();
    containerRegistry.Register<IAppService, OtherService>(typeof(OtherService).FullName);
}

目的是将DebugService / IDebugService和OtherService / IOtherService注册/映射为单例,这将返回相同的实例,但IAppService作为每个实例的命名实例,因此可以注册一个以上的IAppService.任何获取集合的调用都将包含DebugService和OtherService的单例.

第二部分是给我一个问题.在构造函数中获取IAppService的集合总是会生成新的实例.所以,如果我有这个:

public SomeViewModel(
    IModuleMessageBus messageBus
    , IDebugService debugService
    , IEnumerable<IAppService> services
)   {   }

public AnotherViewModel(
    IModuleMessageBus messageBus
    , IDebugService debugService
)   {   }

将会发生的情况是DebugService的构造函数将被击中两次.一次是为两个构造函数的IDebugService注入,另一次是为IEnumerable的注入.如果我注释掉,则IEnumerable< IAppService>服务,那么它只会被击中一次.如何拥有一个服务实例和一个服务实例,但仍要向其他接口注册它们以获得集合.

更新

感谢Haukinger的响应,我看了Prism的github,因为该重载没有被模块暴露.原来他们在7.2中添加了它.它的最新预览(截至撰写本文时已满5天)已合并到:

https://github.com/PrismLibrary/Prism/pull/1668

更新2

不幸的是,这似乎仍然是一个问题.我将注册更改为此,但仍然被击中两次:

containerRegistry.RegisterSingleton<DebugService>();
containerRegistry.RegisterSingleton<IDebugService, DebugService>();
containerRegistry.GetContainer().RegisterSingleton(
    typeof(IAppService)
    , typeof(DebugService)
    , typeof(DebugService).FullName
);

containerRegistry.RegisterSingleton<OtherService>();
containerRegistry.RegisterSingleton<IOtherService, OtherService>();
containerRegistry.GetContainer().RegisterSingleton(
    typeof(IAppService)
    , typeof(OtherService)
    , typeof(OtherService).FullName
);

将PRISM升级到预览不会有什么区别,因为它仍然引用相同的统一版本.但是更新unity软件包会破坏Prism,因为它们包含制动更改(看起来像Unity.Abstraction中的样子).

谢谢哈金格

豪金格(Haukinger)使我走上了正确的轨道,因此如果有帮助,请给他撞个撞!

由于棱镜7(当前)使用的是Unit Container 5.8 / Unity Abstraction 3,因此我们必须使用被标记为已过时且即将被删除的InjectionFactory.为了使上述工作正常进行,我必须这样做(很糟糕):

containerRegistry.RegisterSingleton<DebugService>();
containerRegistry.RegisterSingleton<IDebugService, DebugService>();
//Manually map the registration resolve
containerRegistry.GetContainer().RegisterType<IAppService>(
    typeof(DebugService).FullName
    , new InjectionFactory(c => c.Resolve<DebugService>())
);

containerRegistry.RegisterSingleton<OtherService>();
containerRegistry.RegisterSingleton<IOtherService, OtherService>();
//Manually map the registration resolve
containerRegistry.GetContainer().RegisterType<IAppService>(
    typeof(OtherService).FullName
    , new InjectionFactory(c => c.Resolve<OtherService>())
);

解决方法:

如果您这样临时注册

containerRegistry.Register<IAppService, DebugService>(typeof(DebugService).FullName);

然后每次都应解决一个新的DebugService的预期行为.

如果只希望存在一个DebugService实例,请将其注册为单例:

containerRegistry.RegisterSingleton<IAppService, DebugService>(typeof(DebugService).FullName);

有关Unity 5在这里做什么以及为什么这样做的详细说明(与旧版本不同),请查看this wiki page on github.

编辑:这有点复杂,并且解决方案看起来相当多的替代方法…

container.RegisterSingleton<Service>();
container.RegisterFactory<ISingleInterface>( x => x.Resolve<Service>() );
container.RegisterFactory<IEnumeratedInterface>( "service", x => x.Resolve<Service>() );

这全部用于IUnityContainer,您必须使用GetContainer()扩展从IContainerRegistry获取它.

进一步阅读at unity’s github.根据您的统一版本,您可以/必须使用InjectionFactory而不是RegisterFactory.

上一篇:从PRISM开始学WPF(三)Prism-Region-更新至Prism7.1


下一篇:c# – Prism NavigationService获取以前的视图名称