wpf - MVVMLight ViewModelLocator 注册数据服务

标签 wpf silverlight mvvm mvvm-light viewmodellocator

这个问题可能看起来很幼稚,但我无法理解 ViewModelLocator.cs 文件中的这段代码:

static ViewModelLocator()
{
    ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

    if (ViewModelBase.IsInDesignModeStatic)
    {
        SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
    }
    else
    {
        SimpleIoc.Default.Register<IDataService, DataService>();         
    }

    SimpleIoc.Default.Register<MainViewModel>();
}

我看到我们使用 DataService 来获取数据(例如从 WCF 服务)并将其分配给 MainViewModel。但是如果我注册了多个 ViewModel 怎么办?像这样:

static ViewModelLocator()
{
    ....
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<Page2ViewModel>();
}

假设我有另一个 DataService(例如 DataService2),但这个我将与 Page2ViewModel 一起使用。我怎样才能做到这一点?

另外,如果有人可以帮助我(甚至给我一个阅读链接)上面的代码。我不知道这意味着什么。

最佳答案

您没有分配任何 IDataServiceMainViewModel这里。你正在注册一个类型映射,所以你的容器会知道它应该返回一个 DataService每当 IDataService必需的。

这与 有关依赖注入(inject) http://en.wikipedia.org/wiki/Dependency_injection

DI 容器 汽车线依赖项,因此当您需要特定类型时,您可以调用
ServiceLocator.Current.GetInstance<IDataService>()
或者

ServiceLocator.Current.GetInstance<MainViewModel>()

等等。如果它可以构建它(所以你注册了你的类型),它将为你解析完整的依赖图。

例如,如果您的 MainViewModel构造函数依赖于 IDataService ,并且您不在设计模式下,DataService将注入(inject) MainViewModel构造函数。不要害怕注入(inject)的流行语,它只是使用适当的参数调用 MainViewModel 构造函数:)。

所以,MainViewModel不会干扰 Page2ViewModel这里。

我为您制作了一个简单的示例来演示发生了什么(我使用了 Unity,http://unity.codeplex.com/,但语法几乎相同):

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();
        container.RegisterType<IService, Service1>();
        container.RegisterType<IService, Service2>("MySpecificService");
        container.RegisterType<IRepository, Repository>();
        ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));

        var viewModel = ServiceLocator.Current.GetInstance<MainViewModel>();
        viewModel.Foo();
    }
}

interface IService
{
}

interface IRepository
{   
}

class Service1 : IService
{
    public Service1(IRepository repository)
    {
        Console.WriteLine("Service1 created");
    }
}

class Service2 : IService
{
    public Service2()
    {
        Console.WriteLine("Service2 created");
    }
}

class Repository : IRepository
{
    public Repository()
    {
        Console.WriteLine("Repository created");
    }
}

class MainViewModel
{
    public MainViewModel(IService service)
    {
        Console.WriteLine("MainViewModel created");
    }

    public void Foo()
    {
        var specificService = ServiceLocator.Current.GetInstance<IService>("MySpecificService");
    }
}

输出是:

Repository created
Service1 created
MainViewModel created
Service2 created

因为您需要 MainViewModel (也许在 SimpleIoC 中你也需要注册 MainViewModel,在 Unity 中,它可以解析具体的类而不需要映射),容器试图创建一个,但它意识到 MainViewModel需要 IService ,它会从映射中找到默认值,即 Service1 ,但它意识到 Service1需要 IRepository ,它会找到默认的,所以它可以传递一个 RepositoryService1构造函数,然后是 Service1 MainViewModel 的实例构造函数。所有的依赖关系都解决了。
Foo call 是一个示例,您可以如何将多个类型注册到同一接口(interface)。依赖注入(inject)是一个更大的话题,但 Autowiring 是其中的重要组成部分。

关于wpf - MVVMLight ViewModelLocator 注册数据服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9052180/

相关文章:

wpf - 将只读 GUI 属性推回 ViewModel

ios - 如何将正确的 viewModel 注入(inject)单个 viewController

android - 如何使用 Koin 对 MVVM 进行单元测试?

c# - 如何对 Visual3D 或 UIElement3D 等 3D 元素使用数据绑定(bind)

.net - WPF - 为什么 ContextMenu 项目适用于 ListBox 但不适用于 ItemsControl?

c# - 如何在 Silverlight 的 Canvas 上动态放置控件?

visual-studio-2008 - Silverlight 开发 [Visual Studio 2008 与 Expression Blend]

WPF Observablecollection 与 ListView 的 INotifyPropertyChanged 不起作用

wpf - 如何将 Ribbon 控件绑定(bind)到我的 ViewModel?

javascript - 将 JavaScript 变量传输到 Silverlight 时出现问题