MVVMLight ViewModelLocator注册dataservice

时间:2012-01-29 09:26:44

标签: 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一起使用。我怎么能这样做?

此外,如果有人可以帮助我(或者甚至给我一个阅读链接)关于上述代码。我不知道这意味着什么。

1 个答案:

答案 0 :(得分:21)

您未在此处为IDataService分配任何MainViewModel。您正在注册类型映射,因此只要需要DataService,您的容器就会知道它应该返回IDataService

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

有关

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

ServiceLocator.Current.GetInstance<IDataService>()

ServiceLocator.Current.GetInstance<MainViewModel>()

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

例如,如果您的MainViewModelIDataService具有构造函数依赖关系,并且您未处于设计模式,则会向DataService构造函数注入MainViewModel。不要害怕流行语注入,它只是使用适当的参数调用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中,它可以解析具体的类而不需要映射),容器试图创建一个,但它意识到{{1}需要一个MainViewModel,它会从映射中找到默认值IService,但它会意识到Service1需要一个Service1,它会找到默认值IRepository ,因此它可以将Repository传递给Service1构造函数,然后将Service1实例传递给MainViewModel构造函数。所有依赖项都已解决。

Foo调用是一个示例,说明如何将多种类型注册到同一个接口。依赖注入是一个更大的主题,但自动布线是其中的一个重要部分。

相关问题