这个问题可能看起来很幼稚,但我无法理解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一起使用。我怎么能这样做?
此外,如果有人可以帮助我(或者甚至给我一个阅读链接)关于上述代码。我不知道这意味着什么。
答案 0 :(得分:21)
您未在此处为IDataService
分配任何MainViewModel
。您正在注册类型映射,因此只要需要DataService
,您的容器就会知道它应该返回IDataService
。
这与依赖注入 http://en.wikipedia.org/wiki/Dependency_injection
有关DI容器自动连接依赖项,因此当您需要特定类型时,可以调用
ServiceLocator.Current.GetInstance<IDataService>()
或
ServiceLocator.Current.GetInstance<MainViewModel>()
等。 如果它可以构建它(所以你注册了你的类型),它将为你解析完整的依赖图。
例如,如果您的MainViewModel
对IDataService
具有构造函数依赖关系,并且您未处于设计模式,则会向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
调用是一个示例,说明如何将多种类型注册到同一个接口。依赖注入是一个更大的主题,但自动布线是其中的一个重要部分。