Intro
Dalam MVVM, praktik yang biasa dilakukan adalah meminta Views menemukan ViewModels mereka dengan menyelesaikannya dari penampung injeksi ketergantungan (DI). Ini terjadi secara otomatis ketika container diminta untuk menyediakan (menyelesaikan) sebuah instance dari kelas View. Penampung memasukkan ViewModel ke dalam Tampilan dengan memanggil konstruktor Tampilan yang menerima parameter ViewModel; skema ini disebut inversion of control (IoC).
Manfaat DI
Manfaat utama di sini adalah bahwa penampung dapat dikonfigurasi pada waktu proses dengan petunjuk tentang cara menyelesaikan jenis yang kami minta darinya. Hal ini memungkinkan testabilitas yang lebih besar dengan menginstruksikannya untuk menyelesaikan jenis (Views dan ViewModels) yang kita gunakan saat aplikasi kita benar-benar berjalan, tetapi menginstruksikannya secara berbeda saat menjalankan pengujian unit untuk aplikasi tersebut. Dalam kasus terakhir, aplikasi bahkan tidak akan memiliki UI (tidak berjalan; hanya pengujiannya) sehingga penampung akan menyelesaikan tiruan sebagai ganti jenis "normal" yang digunakan saat aplikasi berjalan.
Masalah yang berasal dari DI
Sejauh ini kita telah melihat bahwa pendekatan DI memungkinkan kemudahan pengujian untuk aplikasi dengan menambahkan lapisan abstraksi selama pembuatan komponen aplikasi. Ada satu masalah dengan pendekatan ini: pendekatan ini tidak cocok dengan desainer visual seperti Microsoft Expression Blend.
Masalahnya adalah bahwa dalam proses aplikasi normal dan pengujian unit, seseorang harus menyiapkan container dengan instruksi tentang tipe apa yang harus diselesaikan; Selain itu, seseorang harus meminta penampung untuk menyelesaikan Tampilan sehingga ViewModels dapat dimasukkan ke dalamnya.
Namun, dalam waktu desain tidak ada kode kami yang berjalan . Perancang mencoba menggunakan refleksi untuk membuat contoh Tampilan kami, yang berarti:
- Jika konstruktor Tampilan memerlukan contoh ViewModel, perancang tidak akan dapat membuat contoh Tampilan sama sekali - ini akan menghasilkan kesalahan dengan cara yang terkontrol
- Jika View memiliki konstruktor tanpa parameter, View akan dipakai, tetapi
DataContext
akan null
begitu kita mendapatkan tampilan "kosong" di desainer - yang tidak terlalu berguna
Masuk ke ViewModelLocator
ViewModelLocator adalah abstraksi tambahan yang digunakan seperti ini:
- Tampilan itu sendiri membuat instance ViewModelLocator sebagai bagian dari sumber dayanya dan menghubungkan DataContext-nya ke properti ViewModel pelacak
- Locator entah bagaimana mendeteksi jika kita dalam mode desain
- Jika tidak dalam mode desain, locator mengembalikan ViewModel yang diselesaikannya dari kontainer DI, seperti dijelaskan di atas
- Jika dalam mode desain, pencari lokasi mengembalikan ViewModel "tiruan" yang tetap menggunakan logikanya sendiri (ingat: tidak ada kontainer dalam waktu desain!); ViewModel ini biasanya sudah terisi sebelumnya dengan data dummy
Tentu saja ini berarti bahwa View harus memiliki konstruktor tanpa parameter untuk memulai (jika tidak, desainer tidak akan dapat membuatnya).
Ringkasan
ViewModelLocator adalah idiom yang memungkinkan Anda menyimpan manfaat DI dalam aplikasi MVVM Anda sekaligus memungkinkan kode Anda berfungsi baik dengan desainer visual. Ini terkadang disebut "daya campuran" dari aplikasi Anda (mengacu pada Campuran Ekspresi).
Setelah mencerna hal di atas, lihat contoh praktis di sini .
Terakhir, menggunakan template data bukanlah alternatif untuk menggunakan ViewModelLocator, tetapi alternatif untuk menggunakan pasangan View / ViewModel eksplisit untuk bagian UI Anda. Seringkali Anda mungkin menemukan bahwa tidak perlu menentukan Tampilan untuk ViewModel karena Anda bisa menggunakan templat data sebagai gantinya.