Ini sebenarnya mudah dilakukan setelah Anda memahami bahwa DI adalah tentang pola dan prinsip , bukan teknologi.
Untuk merancang API dengan cara AG-agnostik DI, ikuti prinsip-prinsip umum ini:
Program ke antarmuka, bukan implementasi
Prinsip ini sebenarnya adalah kutipan (dari memori meskipun) dari Pola Desain , tetapi harus selalu menjadi tujuan nyata Anda . DI hanyalah sarana untuk mencapai tujuan itu .
Terapkan Prinsip Hollywood
Prinsip Hollywood dalam istilah DI mengatakan: Jangan panggil DI Container, itu akan memanggil Anda .
Jangan pernah secara langsung meminta dependensi dengan memanggil kontainer dari dalam kode Anda. Tanyakan secara implisit dengan menggunakan Constructor Injection .
Gunakan Injeksi Konstruktor
Ketika Anda membutuhkan dependensi, mintalah secara statis melalui konstruktor:
public class Service : IService
{
private readonly ISomeDependency dep;
public Service(ISomeDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
public ISomeDependency Dependency
{
get { return this.dep; }
}
}
Perhatikan bagaimana kelas Layanan menjamin invariannya. Setelah sebuah instance dibuat, ketergantungan dijamin akan tersedia karena kombinasi Klausa Penjaga dan readonly
kata kunci.
Gunakan Pabrik Abstrak jika Anda membutuhkan objek berumur pendek
Ketergantungan yang disuntikkan dengan Constructor Injection cenderung berumur panjang, tetapi kadang-kadang Anda membutuhkan objek berumur pendek, atau untuk membangun ketergantungan berdasarkan pada nilai yang hanya diketahui pada saat run-time.
Lihat ini untuk informasi lebih lanjut.
Menulis hanya pada Momen Bertanggung Jawab Terakhir
Jagalah agar benda-benda tetap terpisah sampai akhir. Biasanya, Anda bisa menunggu dan memasang semuanya di titik masuk aplikasi. Ini disebut Root Komposisi .
Lebih detail di sini:
Sederhanakan menggunakan Facade
Jika Anda merasa bahwa API yang dihasilkan menjadi terlalu rumit untuk pengguna pemula, Anda selalu dapat memberikan beberapa kelas Fasad yang merangkum kombinasi ketergantungan umum.
Untuk memberikan Fasad yang fleksibel dengan tingkat penemuan yang tinggi, Anda dapat mempertimbangkan untuk menyediakan Pembuat Fluent. Sesuatu seperti ini:
public class MyFacade
{
private IMyDependency dep;
public MyFacade()
{
this.dep = new DefaultDependency();
}
public MyFacade WithDependency(IMyDependency dependency)
{
this.dep = dependency;
return this;
}
public Foo CreateFoo()
{
return new Foo(this.dep);
}
}
Ini akan memungkinkan pengguna untuk membuat Foo default dengan menulis
var foo = new MyFacade().CreateFoo();
Namun, akan sangat mudah ditemukan bahwa mungkin untuk menyediakan ketergantungan khusus, dan Anda dapat menulis
var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();
Jika Anda membayangkan bahwa kelas MyFacade merangkum banyak dependensi yang berbeda, saya harap jelas bagaimana ini akan memberikan default yang tepat sambil tetap membuat diperpanjang dapat ditemukan.
FWIW, lama setelah menulis jawaban ini, saya memperluas konsep-konsep di sini dan menulis posting blog yang lebih panjang tentang DI-Friendly Libraries , dan sebuah postingan tentang DI-Friendly Frameworks .