DI'nin teknoloji değil kalıplar ve ilkeler ile ilgili olduğunu anladıktan sonra bunu yapmak basittir .
API'yi DI Container-agnostik bir şekilde tasarlamak için şu genel ilkeleri izleyin:
Bir uygulamaya değil, bir arayüze programlayın
Bu ilke aslında Tasarım Desenlerinden bir alıntıdır (ancak bellekten) , ancak her zaman gerçek hedefiniz olmalıdır . DI sadece bu amaca ulaşmak için bir araçtır .
Hollywood Prensibini Uygula
DI terimleriyle Hollywood Prensibi diyor ki: DI Container'ı arama, seni arayacak .
Kodunuzun içinden bir kapsayıcı arayarak asla doğrudan bağımlılık istemeyin. Yapıcı Enjeksiyon kullanarak örtük olarak isteyin .
Yapıcı Enjeksiyonu Kullan
Bir bağımlılığa ihtiyacınız olduğunda , yapıcı aracılığıyla statik olarak isteyin :
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; }
}
}
Service sınıfının değişmezlerini nasıl garanti ettiğine dikkat edin. Bir örnek oluşturulduktan sonra, Guard Clause ve readonly
anahtar kelimenin birleşimi nedeniyle bağımlılığın kullanılabilir olması garanti edilir .
Kısa ömürlü bir nesneye ihtiyacınız varsa Abstract Factory kullanın
Konstrüktör Enjeksiyonu ile enjekte edilen bağımlılıklar uzun ömürlü olma eğilimindedir, ancak bazen kısa ömürlü bir nesneye ihtiyacınız vardır veya bağımlılığı sadece çalışma zamanında bilinen bir değere dayanarak inşa edebilirsiniz.
Bkz bu fazla bilgi için.
Yalnızca Son Sorumlu An'da yaz
Nesneleri sonuna kadar ayırın. Normalde, uygulamanın giriş noktasında her şeyi bekleyebilir ve kablolayabilirsiniz. Buna Kompozisyon Kökü denir .
Daha fazla ayrıntı burada:
Cephe Kullanarak Basitleştirin
Ortaya çıkan API'nin acemi kullanıcılar için çok karmaşık hale geldiğini düşünüyorsanız, her zaman ortak bağımlılık kombinasyonlarını kapsayan birkaç Cephe sınıfı sağlayabilirsiniz .
Yüksek derecede keşfedilebilirliğe sahip esnek bir Cephe sağlamak için Akıcı İnşaatçılar sağlamayı düşünebilirsiniz. Bunun gibi bir şey:
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);
}
}
Bu, kullanıcının yazarak varsayılan bir Foo oluşturmasına olanak tanır
var foo = new MyFacade().CreateFoo();
Bununla birlikte, özel bir bağımlılık sağlamanın mümkün olduğu çok keşfedilebilir ve yazabilirsiniz.
var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();
MyFacade sınıfının birçok farklı bağımlılığı kapsadığını hayal ederseniz, genişletilebilirliği hala keşfedilebilir hale getirirken uygun varsayılanları nasıl sağlayacağını umarım.
FWIW, bu cevabı yazdıktan çok sonra, buradaki kavramları genişlettim ve DI-Friendly Libraries hakkında daha uzun bir blog yazısı ve DI-Friendly Frameworks hakkında bir eşlik yazısı yazdım .