将单例注册为 Prism 7 的接口集合
Register singletons as collection of Interfaces with Prism 7
我正在将使用 MEF for IOC 的 Prim 6 转换为 Prism 7 Unity,因为不再支持 MEF。我必须应对的最大差异是 MEF 中的假设,即默认情况下一切都是单例,而 Unity 倾向于假设相反。
我已经转换了大部分,但我 运行 做的一件事是让构造函数通过集合引用单例。例如,我有这些接口和 类:
public interface IAppService { }
public interface IDebugService : IAppService { }
public class DebugService : IDebugService { }
public interface IOtherService : IAppService { }
public class OtherService : IOtherService { }
with DebugService
and OtherService
registers as singletons and mapped to both of their respective interfaces:
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
是 registered/mapped 作为单例的 return 相同的实例但是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
那么它只会被击中一次。我怎样才能拥有一个且只有一个服务实例,但仍将它们注册到其他接口以作为集合获取。
更新
感谢 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 升级到预览版不会有什么不同,因为它仍然引用相同的统一版本。但是更新统一包会破坏 Prism,因为它们包含制动更改(看起来像 Unity.Abstraction)。
感谢 HAUKINGER 的回答
Haukinger 让我走上了正确的轨道,如果这有帮助,请给他点赞!!
由于 prism 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。
编辑:有点复杂,解决方案看起来有点workaround-ish...
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。根据您的统一版本,您 can/have 使用 InjectionFactory
而不是 RegisterFactory
。
我正在将使用 MEF for IOC 的 Prim 6 转换为 Prism 7 Unity,因为不再支持 MEF。我必须应对的最大差异是 MEF 中的假设,即默认情况下一切都是单例,而 Unity 倾向于假设相反。
我已经转换了大部分,但我 运行 做的一件事是让构造函数通过集合引用单例。例如,我有这些接口和 类:
public interface IAppService { }
public interface IDebugService : IAppService { }
public class DebugService : IDebugService { }
public interface IOtherService : IAppService { }
public class OtherService : IOtherService { }
with DebugService
and OtherService
registers as singletons and mapped to both of their respective interfaces:
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
是 registered/mapped 作为单例的 return 相同的实例但是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
那么它只会被击中一次。我怎样才能拥有一个且只有一个服务实例,但仍将它们注册到其他接口以作为集合获取。
更新
感谢 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 升级到预览版不会有什么不同,因为它仍然引用相同的统一版本。但是更新统一包会破坏 Prism,因为它们包含制动更改(看起来像 Unity.Abstraction)。
感谢 HAUKINGER 的回答
Haukinger 让我走上了正确的轨道,如果这有帮助,请给他点赞!!
由于 prism 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。
编辑:有点复杂,解决方案看起来有点workaround-ish...
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。根据您的统一版本,您 can/have 使用 InjectionFactory
而不是 RegisterFactory
。