早些时候,我写了这个问题,关于让MainViewModel实现接口的方式取决于我的Universal App中正在运行的项目。
在实现了MVVM指示灯之后,我就可以通过以下方式注册我的VM:
SimpleIoc.Default.Register<MainViewModel>();
它还提供了在CTOR中使用接口注册VM的机会,如下所示:
SimpleIoc.Default.Register<IDataService, DataService>();
设置如下:
我有2个项目,Windows和WindowsPhone。在我的VM(位于PCL中)中,我的MainViewModel带有ctor中的ICameraCaller。这些项目都有一个实现ICameraCaller的类,并且我想根据我运行的项目,将CameraCaller的“正确”实现传递给CTOR。
因此,有人告诉我DI是必经之路。对我来说,这是一个相当新的话题,我已经坚持了很长时间。
在我看来,这应该是一项相当普通的任务?根据正在运行的项目将接口的实现传递给VM。
这是MainViewModel的ctor:
private ICameraCaller _cameraCaller;
public MainViewModel(ICameraCaller cameraCaller)
{
_cameraCaller = cameraCaller;
}
考虑到我不知道将使用哪种实现,我不了解如何在ViewModelLocator中向我的视图模型注册接口。即使我知道。我无法访问其他项目中的实现。我一定对这个问题全都错了。
首先:使用便携式版本的mvvm light MVVMLight.portable
。我还建议您使用一些更高级的IoC
容器-我个人更喜欢Ninject
(也有称为的便携式版本Ninject.Portable
)-它可以满足我的所有需求。从获取它Nuget Package Manager
。
第二个-创建名为ViewModelLocator
(对于Windows Phone和Windows Modern不同)的类,它将充当您所谓的ApplicationCore
(依赖项注入容器所在的位置)。
例子:
public class ViewModelLocator
{
private readonly IKernel _dependenciesContainer;
public ViewModelLocator()
{
_dependenciesContainer = new StandardKernel(new ApplicationKernelModule());
}
public MainViewModel Main { get { return _dependenciesContainer.Get<MainViewModel>() } }
}
public class ApplicationKernelModule : NinjectModule
{
public override void Load()
{
Bind<ICameraCaller>().To<DesktopCameraCaller>();
}
}
public class DesktopCameraCaller : ICameraCaller
{
// here lies Windows Modern implementation of camera caller
}
在App.xaml中,将您添加ViewModelLocator
为StaticResource
:
<Application
x:Class="YourApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:YouNamespace"
xmlns:viewModel="using:ViewModelLocatorNamespace">
<Application.Resources>
<ResourceDictionary>
<viewModel:ViewModelLocator x:Key="ViewModelLocator"/>
</ResourceDictionary>
</Application.Resources>
并在您的MainView中添加绑定到适当的ViewModel:
DataContext={Binding Source={StaticResource ViewModelLocator}, Path=Main}
对Windows Phone项目重复完全相同的步骤,但在ApplicationModule中将绑定到Windows Phone实现,例如:Bind<ICameraController>().To<WindowsPhoneCameraController>()
。
那里发生了什么?您使用Inversion of Control
称为Ninject
“将”接口“绑定”到具体类的库。这意味着-当您调用IKernel.Get<Type>()
并在创建对象时Ninject
看到构造函数中的任何位置时,ICameraControl
它将在其中创建新ModernCameraControl
对象。您创建ViewModelLocator
了一个简单的位置来存储“ Dependency Injection Resolver”(称为IKernel)-因此,您不必在任何地方都使用丑陋的服务定位器模式和静态引用Kernel
。当然,我以简化版描述了它-Ninject
您可以做其他很棒的事情,例如进行范围界定(例如,您可以将接口注册为单例的类-在绑定的任何位置都存在相同的对象插入),您可以在注入类时添加条件逻辑(检查Bind<T>().To<T>().WhenInjectedTo/WhenInjectedExactlyTo
,Bind<T>().ToMethod(..)
等等)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句