我最近有机会创建一个新的基于棱镜的应用程序。我使用6.3版本已经有一段时间了,但是看到Prism 7已经退出预发行版本,想尝试一下。我使用Prism模板包创建了一个新的棱镜应用程序,并且所有功能都能按预期工作。我像在6.3中通常所做的那样更新了视图模型以传递到Container中,因此我可以解析一些对象,以便稍后向视图提供信息,在6.3中,我将执行以下操作:
public MainWindowViewModel(IRegionManager aRegionManager,
IUnityContainer aUnityContainer) : base()
现在在7.1.0.431中,我试图做同样的事情,但是更新了接口以说明新的IOC抽象。
public MainWindowViewModel(IRegionManager aRegionManager,
IContainerProvider aContainerProvider,
IContainerRegistry aContainerRegistry) : base()
这会从ViewModelLocator.AutoWireViewModel生成IContainerX参数的异常。
System.Exception {Unity.Exceptions.ResolutionFailedException}
{"Resolution of the dependency failed, type = 'Sample.ViewModels.MainWindowViewModel', name = '(none)'.\nException occurred while: while resolving.\nException is: InvalidOperationException - The current type, Prism.Ioc.IContainerProvider, is an interface and cannot be constructed. Are you missing a type
这就像我缺少引用一样,但是我将该类型传递给应用程序的RegisterTypes调用,因此应该找到所有引用。对于新的7.X版本,我做错什么了吗?
编辑:按@mnistic
这是App.xaml.cs提供的模板包中的代码,其中传递了IContainerRegistry。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//containerRegistry is a valid instance here
}
更新:
再深入一点,传递给RegisterTypes的IContainerRegistry列出了在调用该方法时可用的所有类型/接口。它注册了一个IUnityContainer实例。在创建项目时,我为IOC选择了Unity,但我可能会错误地认为IContainerRegistry正在将客户端隐藏在实际的实现中。如果我更新ViewModel构造函数以接受IUnityContainer的对象,它将正确解析。
public MainWindowViewModel(IRegionManager aRegionManager,
IUnityContainer aContainerProvider) : base()
这是理想的行为吗?
答案 0 :(得分:2)
请勿执行此操作。您不希望将容器放在解决方案的根目录之外,这很可怕,需要进行测试,否则会隐藏明显的依赖关系,并且毫无益处。
如果需要服务,请直接注射。如果需要工厂,请注入Func<IProduct>
或IHandcraftedFactory
。如果您需要所有实现ISomething
的注册类型,请注入ISomething[]
或IEnumerable<ISomething>
。
产品的示例(复杂)工厂:
public interface IFactory
{
IProduct CreateProduct( int someParameter );
}
internal class DeviceFactory : IFactory
{
public DeviceFactory( IService service )
{
_service = service;
}
public IProduct CreateProduct( int someParameter ) => new Device( someParameter, _someService );
private readonly IService _service;
private class Device : IProduct
{
public Device( int someParameter, IService aDependency )
{
// ...
}
}
}
如果Device
没有someParameter
,则跳过IFactory
和DeviceFactory
,而只注入Func<IProduct>
... Device
然后收到其IService
。
请记住-容器在那里可以简化事情:它可以解决依赖关系,创建实例并管理单例。但是,如果您没有容器,那么一切都会正常进行,就像单元测试中那样。您只需手动创建所有依赖项。
回到当前的主题-IContainerRegistry
只是IUnityContainer
周围的一个短而薄的包装器(在您的情况下),因此在使用不同应用程序的不同应用程序中,注册码看起来有些相似容器。 Prism尝试通过不注册IContainerRegistry
来朝着正确的方向(请参见上文)推动您,以便在应该使用它的地方使用它(在模块初始化期间)并防止您避免在其他地方使用它(使其无法注入)。