SimpleIoc.Default.GetInstance和ServiceLocator.Current.GetInstance之间有区别吗

时间:2012-12-26 18:23:28

标签: inversion-of-control mvvm-light

我正在使用适用于Windows 8的MVVM Light版本4;它包括SimpleIOC。在各种示例中,我有时会看到基于SimpleIoc请求对象的代码...有时它基于ServiceLocator ......

示例包括:

userToken = SimpleIoc.Default.GetInstance();

mainVM = ServiceLocator.Current.GetInstance();

使用SimpleIoc.Default.GetInstance和ServiceLocator.Current.GetInstance有什么区别?

如果没有区别,ServiceLocator是否让我可以选择改变我想要使用的IOC库的想法? ServiceLocator是否只提供了一个额外的抽象层,如果我对SimpleIoc感到满意,那么它是无关紧要的;或者,ServiceLocator是否会执行其他一些对IOC新手来说不明显的有用魔法?

感谢您的见解!

2 个答案:

答案 0 :(得分:9)

在ViewModelLocator类中,您可能有以下代码行:

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

SimpleIoc实现IServiceLocator接口,这意味着ServiceLocator会在调用时将其用作DI源。

编辑:

好吧,人们想要“全脂而且不要吝啬奶油”的答案。我们走了!

ServiceLocator基本上是一个shell。服务定位器的代码是:

public static class ServiceLocator
{
  private static ServiceLocatorProvider currentProvider;

  public static IServiceLocator Current
  {
    get
    {
      return ServiceLocator.currentProvider();
    }
  }

  public static void SetLocatorProvider(ServiceLocatorProvider newProvider)
  {
    ServiceLocator.currentProvider = newProvider;
  }
}
是的,就是这样。

什么是ServiceLocatorProvider?它是一个委托,它返回一个实现IServiceLocator的对象。

SimpleIoc实施IServiceLocator。所以当我们这样做时:

ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

我们将SimpleIoc对象放入ServiceLocator。您现在可以使用其中任何一个,因为无论是调用ServiceLocator.Current还是SimpleIoc.Default,您都会返回相同的对象实例。

那么,

之间有什么区别吗?
userToken = SimpleIoc.Default.GetInstance();

mainVM = ServiceLocator.Current.GetInstance();

不。没有。两者都是暴露静态属性的单例,这是IServiceLocator的实现。如上所述,无论您调用哪个对象,都会返回实现IServiceLocator的对象实例。

为什么您可能希望用户的唯一原因ServiceLocator.Current.GetInstance(),而不是SimpleIoc.Default.GetInstance()是,在未来的某个时候,你可能会改变DI容器,如果你使用ServiceLocator,你赢了不得不改变你的代码。

答案 1 :(得分:0)

基于Bugnion先生在MSDN上的article(在“注册类的各种方法”一节中),我假设IoC提供商的可互换性是使用ServiceLocator的唯一原因。

正如@FasterSolutions所述,SimpleIoc实现了IServiceLocator,因此我怀疑与你的关于抽象层的声明相反。我认为你应该使用ServiceLocator,但这没有经验证据;也许有人可以证明我错了(?)