我开始使用Microsoft的Prism框架和Unity作为WPF应用程序,主要是为了自学一些新概念。
我一直在努力理解依赖注入以及如何将Unity与我的视图模型一起使用,但我对自己正在做的事情没有足够的把握,甚至不知道我做错了什么。
因此,我将介绍我所处的情景,并希望有人能帮助我了解我出错的地方。
让我们考虑一个EventAggregator场景,ModuleA发布和ModuleB订阅。在我的ModuleA MainWindowViewModel
中,我会有一个像这样的类构造函数:
private IEventAggregator _eventAggregator;
public MainWindowViewModel(IEventAggregator eventAggregator) {
_eventAggregator = eventAggregator;
...
}
现在,当我注册ModuleA MainWindowView
时,我会做这样的事情:
public class ModuleA {
private readonly IRegionManager _regionManager;
public ModuleA(IRegionManager regionManager) {
_regionManager = regionManager;
}
public void Initialize() {
_regionManager.RegisterViewWithRegion("SomeRegion", typeof(MainWindowView));
}
}
然后,在我的项目Bootstrapper.cs
中,我会创建我的ModuleCatalog
:
public class Bootstrapper {
...
protected override void ConfigureModuleCatalog() {
base.ConfigureModuleCatalog();
ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
moduleCatalog.AddModule(typeof(ModuleA.ModuleA));
...
}
}
现在,我可以使用ServiceLocator
在我的ViewModel中实例化我的eventAggregator
,但我正在尝试通过依赖注入,使用IUnityContainer
注册我的ViewModel然后注入我认为必要。此外,我一直看到我实际上应该使用ViewModel的接口(即IMainWindowViewModel
)来分离问题。
有人能指出我可以清除我所遇到的明显混乱的资源吗?我已经阅读过MSDN的Prism快速入门,包括高级MVVM场景,但我不明白如何将指令置于语境中。
答案 0 :(得分:0)
现在,我可以使用
ServiceLocator
在eventAggregator
中实例化我的ViewModel
,但我正在尝试通过依赖注入执行此操作,将ViewModel
注册到IUnityContainer
View
然后根据需要注入ViewModel
。
上面提到了两种不同的机制:
服务定位器与依赖注入
基本选择是服务定位器和依赖注入之间。第一点是两个实现都提供了天真示例中缺少的基本解耦 - 在这两种情况下,应用程序代码都独立于服务接口的具体实现。这两种模式之间的重要区别在于如何为应用程序类提供该实现。使用服务定位器,应用程序类通过发送给定位器的消息明确地请求它。使用注入没有明确的请求,服务出现在应用程序类中 - 因此控制反转。
- Inversion of Control Containers and the Dependency Injection pattern, Martin Fowler。
结论。必须有一个架构决策:“使用哪种机制?”。
此外,我一直看到我应该使用我的
IMainWindowViewModel
(即/** * @param filePath * @param fs * @return list of absolute file path present in given path * @throws FileNotFoundException * @throws IOException */ public static List<String> getAllFilePath(Path filePath, FileSystem fs) throws FileNotFoundException, IOException { List<String> fileList = new ArrayList<String>(); FileStatus[] fileStatus = fs.listStatus(filePath); for (FileStatus fileStat : fileStatus) { if (fileStat.isDirectory()) { fileList.addAll(getAllFilePath(fileStat.getPath(), fs)); } else { fileList.add(fileStat.getPath().toString()); } } return fileList; }
)的界面来区分问题。
这就是依赖倒置原则的应用方式。
依赖性倒置原则:
一个。高级模块不应该依赖于低级模块。两者都应该取决于抽象。
B中。抽象不应该依赖于细节。细节应取决于抽象。
- The Dependency Inversion Principle, Robert C. Martin, 1996。
“详细信息”是具体类型,“抽象”是接口。
有关详细信息,请参阅引用的参考文献。