2012-01-29 8 views
7

Esta pregunta puede parecer ingenuo, pero yo no podía entender este código en el archivo ViewModelLocator.cs:MVVMLight ViewModelLocator registrarse Dataservice

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>(); 
} 

veo que utilizamos un DataService para obtener los datos (de servicio WCF para ejemplo) y asignarlo al MainViewModel. Pero, ¿qué ocurre si registro más de un ViewModel? de esta manera:

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

y vamos a decir que tengo otra DataService (DataService2 por ejemplo), pero éste voy a utilizar con el Page2ViewModel. ¿Cómo puedo hacer eso?

Además, si alguien puede ayudarme (o incluso darme un enlace para leer) sobre el código anterior. No tengo idea de lo que significa.

Respuesta

21

No está asignando ningún IDataService al MainViewModel aquí. Está registrando un mapeo de tipo, por lo que su contenedor sabrá que debe devolver un DataService siempre que se requiera IDataService.

esto está relacionado con la inyección dependenciahttp://en.wikipedia.org/wiki/Dependency_injection

El contenedor DI auto-cables las dependencias, por lo que cuando se necesita un tipo específico, puede llamar

ServiceLocator.Current.GetInstance<IDataService>()

o

ServiceLocator.Current.GetInstance<MainViewModel>() 

etc. Si puede compilarlo (por lo que ha registrado sus tipos), se resolverá el gráfico de dependencia completo para usted.

Por ejemplo, si su MainViewModel tiene una dependencia constructor en IDataService, y usted no está en modo de diseño, un DataService se inyectará a la MainViewModel constructor. No tenga miedo de la palabra de moda inyectada, es solo una llamada al constructor MainViewModel con los parámetros adecuados :).

Por lo tanto, MainViewModel no interferirá con Page2ViewModel aquí.

Hice una muestra simple para que usted pueda demostrar lo que sucede (utilicé Unidad, http://unity.codeplex.com/, pero la sintaxis es casi lo mismo):

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"); 
    } 
} 

la salida es:

Repository created 
Service1 created 
MainViewModel created 
Service2 created 

Porque necesita un MainViewModel (tal vez en SimpleIoC necesita registrar MainViewModel también, en Unity, puede resolver clases concretas sin mapeo), el contenedor intenta crear uno, pero se da cuenta de quenecesita una IService, y se encuentra el defecto de la cartografía, que es Service1, pero se da cuenta de que Service1 necesita una IRepository, y que encuentra el predeterminado, por lo que puede pasar un Repository a la Service1 constructor, entonces la instancia Service1 al constructor MainViewModel. Todas las dependencias resueltas

La llamada Foo es un ejemplo de cómo puede registrar más de un tipo en la misma interfaz. La inyección de dependencia es un tema mucho más grande, pero el auto-cableado es una parte importante de esto.

+0

Gracias, muy útil :) – Qirat

+0

@Qirat welcome :) –

Cuestiones relacionadas