MVVMLight ViewModelLocator注册数据服务

7
这个问题看起来很幼稚,但我不理解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一起使用,我该怎么做呢?
另外,如果有人能帮助我(或甚至给我一个链接阅读)关于上述代码。我不知道它的含义。
1个回答

21
你没有将任何 IDataService 分配给 MainViewModel。你正在注册一种类型映射,因此您的容器将知道在需要 IDataService 时应返回一个 DataService

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

DI 容器会自动连接依赖项,因此当您需要特定类型时,可以调用

ServiceLocator.Current.GetInstance<IDataService>()

ServiceLocator.Current.GetInstance<MainViewModel>()

如果它能够构建它(也就是您已经注册了自己的类型),它将为您解析完整的依赖关系图。

例如,如果您的 MainViewModel 在构造函数中依赖于 IDataService,并且您不在设计模式下,则会向 MainViewModel 构造函数注入一个 DataService。不要被“注入”这个术语所吓倒,它只是使用适当的参数调用 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实例,但发现MainViewModel需要一个IService,于是从映射中找到了默认的,即Service1,但Service1需要一个IRepository,容器又找到了默认的,然后将一个Repository实例传递给Service1构造函数,最后将Service1实例传递给MainViewModel构造函数以解决所有依赖关系。 Foo调用是演示如何将多个类型注册到同一个接口。依赖注入是一个更大的话题,但自动装配是其中重要的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接