2012-01-29 21 views
7

Câu hỏi này có thể trông ngây thơ, nhưng tôi không thể hiểu mã này trong ViewModelLocator.cs file:MVVMLight ViewModelLocator đăng ký 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>(); 
} 

Tôi thấy rằng chúng tôi sử dụng một DataService để lấy dữ liệu (từ dịch vụ WCF cho ví dụ) và gán nó cho MainViewModel. Nhưng nếu tôi đăng ký nhiều hơn một ViewModel thì sao? như thế này:

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

và giả sử tôi có một DataService khác (ví dụ DataService2), nhưng tôi sẽ sử dụng DataService này với Page2ViewModel. Làm thế nào tôi có thể làm điều đó?

Ngoài ra, nếu ai đó có thể giúp tôi (hoặc thậm chí cung cấp cho tôi liên kết để đọc) về mã ở trên. Tôi không biết nó có ý nghĩa gì.

Trả lời

21

Bạn chưa chỉ định bất kỳ số IDataService nào cho số MainViewModel tại đây. Bạn đang đăng ký ánh xạ loại, vì vậy vùng chứa của bạn sẽ nhận thức được rằng cần trả lại DataService bất cứ khi nào yêu cầu IDataService.

này liên quan đến dependency injectionhttp://en.wikipedia.org/wiki/Dependency_injection

Các container DI tự động dây sự phụ thuộc, vì vậy khi bạn cần một loại hình cụ thể, bạn có thể gọi

ServiceLocator.Current.GetInstance<IDataService>()

hoặc

ServiceLocator.Current.GetInstance<MainViewModel>() 

vv Nếu nó có thể xây dựng nó (vì vậy bạn đã đăng ký loại của bạn), nó sẽ giải quyết các đồ thị phụ thuộc đầy đủ cho bạn.

Ví dụ, nếu MainViewModel của bạn có một sự phụ thuộc constructor trên IDataService, và bạn đang không ở trong chế độ thiết kế, một DataService sẽ được tiêm cho các nhà xây dựng MainViewModel. Đừng sợ từ buzzword tiêm, nó chỉ là một cuộc gọi đến các nhà xây dựng MainViewModel với các tham số thích hợp :).

Vì vậy, MainViewModel sẽ không can thiệp với Page2ViewModel tại đây.

tôi đã thực hiện một mẫu đơn giản để bạn có thể chứng minh những gì xảy ra (tôi đã sử dụng Unity, http://unity.codeplex.com/, nhưng cú pháp là gần như giống nhau):

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

đầu ra là:

Repository created 
Service1 created 
MainViewModel created 
Service2 created 

Bởi vì bạn cần MainViewModel (có thể trong SimpleIoC bạn cần phải đăng ký MainViewModel nữa, trong Unity, nó có thể giải quyết các lớp cụ thể mà không cần ánh xạ), thùng chứa cố gắng tạo một, nhưng nó nhận ra rằng.210 cần một IService, và nó tìm thấy một mặc định từ các bản đồ, đó là Service1, nhưng nó nhận ra rằng Service1 cần một IRepository, và nó tìm thấy một mặc định, vì vậy nó có thể vượt qua một Repository để các nhà xây dựng Service1, thì dụ Service1 đến nhà xây dựng MainViewModel. Tất cả các phụ thuộc đều được giải quyết.

Cuộc gọi Foo là ví dụ về cách bạn có thể đăng ký nhiều loại cho cùng một giao diện. Dependency injection là một chủ đề lớn hơn nhiều, nhưng auto-wiring là một phần quan trọng của nó.

+0

Cảm ơn, rất hữu ích :) – Qirat

+0

@Qirat welcome :) –