我正在使用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 { }
使用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> 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
。