注册单例作为与Prism 7的接口收集



我正在使用MEF for IOC转换为PRISM 7统一,因为不再支持MEF。我必须与之抗衡的最大区别是MEF的推定,默认情况下,一切都是单人,而团结则倾向于相反。

我的大部分都转换了,但是我遇到的一件事是通过收藏品就有一个构造函数引用单例。例如,我有这些接口和类:

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

使用DebugServiceOtherService寄存器为单例,并映射到它们的两个接口:

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/IDebugServiceOtherService/IOtherService被注册/映射为单例,该单元将返回相同的实例,但IAppService作为每个实例的命名实例,因此可以注册一个IAppService。任何获取收藏的电话都将包括DebugServiceOtherService的单例。

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

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

将发生的是DebugService的构造函数将被击中两次。一次用于构造函数的IDebugService注入,并再次专门针对IEnumerable。如果我评论, IEnumerable<IAppService> services,则只会命中一次。我如何只有一个和一个服务的实例,但仍会将它们注册为其他接口以获取为收藏。


update

多亏了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
);

将棱镜升级到预览不会有所作为,因为它仍然引用了相同的统一版本。但是,更新统一软件包将破坏棱镜,因为它们包含制动更改(看起来像Unity.abstraction(。


回答感谢Haukinger

haukinger让我走上正确的轨道,所以如果有帮助,请给他一个颠簸!

由于Prism 7(当前(使用单元容器5.8/Unity抽象3,因此我们必须使用标记为过时的InjectionFactory,并将很快删除。要使上述工作,我必须这样做(Soooo gross(:

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实例,请将其注册为Singleton:

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

有关Unity 5在这里做什么以及为什么这样做的详细说明(与较旧版本不同(,请查看Github上的此Wiki页面。

编辑:它更复杂,解决方案看起来有点解决方法...

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

这全部适用于IUnityContainer,您必须通过使用GetContainer()扩展名来从IContainerRegistry获得它。

在Unity的Github上进一步阅读。根据您的Unity版本,您可以/必须使用InjectionFactory而不是RegisterFactory

最新更新