Bağımlılık Ekleme
Not
Bu e-Kitap 2017 baharında yayımlanmıştır ve o zamandan beri güncelleştirilmemiştir. Kitapta değerli kalan çok şey var, ancak bazı malzemeler güncelliğini yitirmiş.
Genellikle, bir nesne örneği oluşturulurken bir sınıf oluşturucu çağrılır ve nesnenin ihtiyaç duyduğu tüm değerler oluşturucuya bağımsız değişken olarak geçirilir. Bu bir bağımlılık ekleme örneğidir ve özellikle oluşturucu ekleme olarak bilinir. Nesnenin ihtiyaç duyduğu bağımlılıklar oluşturucuya eklenir.
Bağımlılık ekleme, arabirim türleri olarak bağımlılıkları belirterek somut türlerin bu türlere bağlı koddan ayrıştırılması sağlar. Genellikle, arabirimler ve soyut türler ile bu türleri uygulayan veya genişleten somut türler arasındaki kayıtların ve eşlemelerin listesini tutan bir kapsayıcı kullanır.
Özellik ayarlayıcı ekleme ve yöntem çağrısı ekleme gibi başka bağımlılık ekleme türleri de vardır, ancak bunlar daha az görülür. Bu nedenle, bu bölüm yalnızca bağımlılık ekleme kapsayıcısı ile oluşturucu ekleme işlemi gerçekleştirmeye odaklanacaktır.
Bağımlılık Eklemeye Giriş
Bağımlılık ekleme, Denetimin Ters Çevrilmesi (IoC) deseninin özelleştirilmiş bir sürümüdür ve burada ters çevrilen sorun, gerekli bağımlılığı elde etme işlemidir. Bağımlılık ekleme ile başka bir sınıf çalışma zamanında bir nesneye bağımlılık eklemekle sorumludur. Aşağıdaki kod örneği bağımlılık ekleme kullanılırken sınıfın ProfileViewModel
nasıl yapılandırıldığını gösterir:
public class ProfileViewModel : ViewModelBase
{
private IOrderService _orderService;
public ProfileViewModel(IOrderService orderService)
{
_orderService = orderService;
}
...
}
Oluşturucu, ProfileViewModel
başka bir IOrderService
sınıf tarafından eklenen bir örneği bağımsız değişken olarak alır. sınıfındaki ProfileViewModel
tek bağımlılık arabirim türündedir. Bu nedenle, ProfileViewModel
sınıfın nesnenin örneğini oluşturmadan IOrderService
sorumlu olan sınıfı hakkında herhangi bir bilgisi yoktur. Nesnesinin örneğini oluşturma IOrderService
ve sınıfına ProfileViewModel
eklemeden sorumlu sınıf, bağımlılık ekleme kapsayıcısı olarak bilinir.
Bağımlılık ekleme kapsayıcıları, sınıf örneklerinin örneğini oluşturacak ve kapsayıcının yapılandırmasına göre yaşam sürelerini yönetecek bir tesis sağlayarak nesneler arasındaki bağlantıyı azaltır. Nesneleri oluşturma sırasında kapsayıcı, nesnenin gerektirdiği tüm bağımlılıkları buna ekler. Bu bağımlılıklar henüz oluşturulmadıysa kapsayıcı önce bağımlılıklarını oluşturur ve çözer.
Not
Bağımlılık ekleme, fabrikalar kullanılarak el ile de uygulanabilir. Ancak kapsayıcı kullanmak, ömür yönetimi ve derleme taraması aracılığıyla kayıt gibi ek özellikler sağlar.
Bağımlılık ekleme kapsayıcısı kullanmanın çeşitli avantajları vardır:
- Kapsayıcı, bir sınıfın bağımlılıklarını bulma ve yaşam sürelerini yönetme gereksinimini ortadan kaldırır.
- Kapsayıcı, sınıfı etkilemeden uygulanan bağımlılıkların eşlenmesine olanak tanır.
- Kapsayıcı, bağımlılıkların sahte olmasına izin vererek test edilebilirliği kolaylaştırır.
- Kapsayıcı, uygulamaya yeni sınıfların kolayca eklenmesini sağlayarak sürdürülebilirliği artırır.
MVVM kullanan bir Xamarin.Forms uygulama bağlamında, bağımlılık ekleme kapsayıcısı genellikle görünüm modellerini kaydetmek ve çözümlemek, hizmetleri kaydetmek ve görünüm modellerine eklemek için kullanılır.
Uygulamada görünüm modeli ve hizmet sınıflarının örneğini yönetmek için TinyIoC kullanan eShopOnContainers mobil uygulamasıyla birçok bağımlılık ekleme kapsayıcısı mevcuttur. TinyIoC, bir dizi farklı kapsayıcı değerlendirildikten sonra seçildi ve iyi bilinen kapsayıcıların çoğuna kıyasla mobil platformlarda üstün performans sunuyor. Gevşek bağlantılı uygulamalar oluşturulmasını kolaylaştırır ve tür eşlemelerini kaydetme, nesneleri çözümleme, nesne yaşam sürelerini yönetme ve bağımlı nesneleri çözümlediğini nesnelerin oluşturucularına ekleme yöntemleri de dahil olmak üzere bağımlılık ekleme kapsayıcılarında yaygın olarak bulunan tüm özellikleri sağlar. TinyIoC hakkında daha fazla bilgi için bkz . TinyIoC on github.com.
TinyIoC'de TinyIoCContainer
türü bağımlılık ekleme kapsayıcısını sağlar. Şekil 3-1'de bu kapsayıcı kullanılırken bir nesne örneği IOrderService
oluşturan ve sınıfına ProfileViewModel
eklenen bağımlılıklar gösterilmektedir.
Şekil 3-1: Bağımlılık ekleme kullanılırken bağımlılıklar
Çalışma zamanında kapsayıcı, bir ProfileViewModel
nesnenin örneğini oluşturabilmesi için önce arabirimin IOrderService
hangi uygulamasının örneklenmesi gerektiğini bilmelidir. Bunun için şunlar gereklidir:
- Arabirimi uygulayan bir nesnenin örneğini oluşturma işlemine
IOrderService
karar veren kapsayıcı. Bu, kayıt olarak bilinir. - Arabirimini uygulayan nesnenin ve nesnesinin örneğini
IOrderService
ProfileViewModel
oluşturan kapsayıcı. Bu çözüm olarak bilinir.
Sonunda uygulama nesnesini kullanmayı ProfileViewModel
tamamlar ve çöp toplama için kullanılabilir hale gelir. Bu noktada, diğer sınıflar aynı örneği paylaşmıyorsa çöp toplayıcı örneği atmalıdır IOrderService
.
İpucu
Kapsayıcıdan bağımsız kod yazma. Uygulamayı her zaman kullanılan bağımlılık kapsayıcısından ayırmaya yönelik kapsayıcıdan bağımsız kod yazmaya çalışın.
Kayıt
Bağımlılıkların bir nesneye eklenebilmesi için önce bağımlılık türlerinin kapsayıcıya kaydedilmesi gerekir. Bir türün kaydedilmesi genellikle kapsayıcıya bir arabirim ve arabirimi uygulayan somut bir tür geçirmeyi içerir.
Kapsayıcıdaki türleri ve nesneleri kod aracılığıyla kaydetmenin iki yolu vardır:
- Kapsayıcıya bir tür veya eşleme kaydedin. Gerektiğinde kapsayıcı, belirtilen türün bir örneğini oluşturur.
- Kapsayıcıdaki mevcut bir nesneyi tekil olarak kaydedin. Gerektiğinde, kapsayıcı var olan nesneye bir başvuru döndürür.
İpucu
Bağımlılık ekleme kapsayıcıları her zaman uygun değildir. Bağımlılık ekleme, küçük uygulamalar için uygun veya yararlı olmayan ek karmaşıklık ve gereksinimler sunar. Bir sınıfın herhangi bir bağımlılığı yoksa veya diğer türler için bir bağımlılık değilse, bunu kapsayıcıya koymak mantıklı olmayabilir. Ayrıca, bir sınıfın türüne tam sayı olan ve hiçbir zaman değişmeyecek tek bir bağımlılık kümesi varsa, bunu kapsayıcıya koymak mantıklı olmayabilir.
Bağımlılık ekleme gerektiren türlerin kaydı bir uygulamadaki tek bir yöntemde gerçekleştirilmelidir ve bu yöntem, uygulamanın sınıfları arasındaki bağımlılıkların farkında olduğundan emin olmak için uygulamanın yaşam döngüsünün başlarında çağrılmalıdır. eShopOnContainers mobil uygulamasında bu, nesnesini oluşturan TinyIoCContainer
sınıfı tarafından ViewModelLocator
gerçekleştirilir ve uygulamada bu nesneye başvuru tutan tek sınıftır. Aşağıdaki kod örneği, eShopOnContainers mobil uygulamasının sınıfındaki nesneyi nasıl bildirdığını TinyIoCContainer
ViewModelLocator
gösterir:
private static TinyIoCContainer _container;
Türler oluşturucuya ViewModelLocator
kaydedilir. Bu, önce aşağıdaki kod örneğinde gösterilen bir TinyIoCContainer
örnek oluşturularak gerçekleştirilir:
_container = new TinyIoCContainer();
Türler daha sonra nesnesine TinyIoCContainer
kaydedilir ve aşağıdaki kod örneği, tür kaydının en yaygın biçimini gösterir:
_container.Register<IRequestProvider, RequestProvider>();
Register
Burada gösterilen yöntem bir arabirim türünü somut bir türle eşler. Varsayılan olarak, her arabirim kaydı tekil olarak yapılandırılır ve böylece her bağımlı nesne aynı paylaşılan örneği alır. Bu nedenle, kapsayıcıda yalnızca tek RequestProvider
bir örnek bulunur ve bir oluşturucu aracılığıyla ekleme IRequestProvider
gerektiren nesneler tarafından paylaşılır.
Somut türler, aşağıdaki kod örneğinde gösterildiği gibi doğrudan bir arabirim türünden eşleme olmadan da kaydedilebilir:
_container.Register<ProfileViewModel>();
Varsayılan olarak, her somut sınıf kaydı, her bağımlı nesnenin yeni bir örnek alması için çok örnekli olarak yapılandırılır. Bu nedenle, çözümlendiğinde ProfileViewModel
yeni bir örnek oluşturulur ve kapsayıcı gerekli bağımlılıklarını ekler.
Çözüm
Bir tür kaydedildikten sonra çözümlenebilir veya bağımlılık olarak eklenebilir. Bir tür çözümlendiğinde ve kapsayıcının yeni bir örnek oluşturması gerektiğinde, tüm bağımlılıkları örneğe ekler.
Genellikle, bir tür çözümlendiğinde üç şeyden biri gerçekleşir:
- Tür kaydedilmemişse kapsayıcı bir özel durum oluşturur.
- Tür tekil olarak kaydedildiyse, kapsayıcı singleton örneğini döndürür. Tür ilk kez çağrılırsa, kapsayıcı gerekirse bunu oluşturur ve buna bir başvuru tutar.
- Tür tekil olarak kaydedilmemişse kapsayıcı yeni bir örnek döndürür ve buna başvuru sağlamaz.
Aşağıdaki kod örneği, daha önce TinyIoC'ye kaydedilmiş olan türün nasıl RequestProvider
çözümlenebileceğini gösterir:
var requestProvider = _container.Resolve<IRequestProvider>();
Bu örnekte TinyIoC'den türün somut türünü IRequestProvider
ve bağımlılıkları çözmesi istenir. Genellikle, Resolve
belirli bir türün örneği gerektiğinde yöntemi çağrılır. Çözümlenen nesnelerin ömrünü denetleme hakkında bilgi için bkz . Çözümlenen Nesnelerin Yaşam Ömrünü Yönetme.
Aşağıdaki kod örneği, eShopOnContainers mobil uygulamasının model türlerini ve bağımlılıklarını nasıl görüntüleyişini gösterir:
var viewModel = _container.Resolve(viewModelType);
Bu örnekte TinyIoC'den istenen görünüm modeli için görünüm modeli türünü çözümlemesi istenir ve kapsayıcı bağımlılıkları da çözer. Türü çözümlerken ProfileViewModel
çözümlenmesi gereken bağımlılıklar bir ISettingsService
nesne ve nesnedir IOrderService
. ve OrderService
sınıflarını kaydederken arabirim kayıtları kullanıldığından SettingsService
TinyIoC, ve OrderService
sınıfları için SettingsService
tekil örnekler döndürür ve sonra bunları sınıfın ProfileViewModel
oluşturucusna geçirir. eShopOnContainers mobil uygulamasının modelleri nasıl oluşturup görünümlerle ilişkilendirmesi hakkında daha fazla bilgi için bkz . Model Bulucuyu Görüntüle ile Modeli Otomatik Olarak Oluşturma.
Not
Kapsayıcıya türleri kaydetme ve çözmenin, özellikle uygulamadaki her sayfa gezintisi için bağımlılıkların yeniden oluşturulması durumunda kapsayıcının her türü oluşturmak için yansıma kullanması nedeniyle performans maliyeti vardır. Çok veya derin bağımlılıklar varsa oluşturma maliyeti önemli ölçüde artabilir.
Çözümlenen Nesnelerin Yaşam Ömrünü Yönetme
Somut bir sınıf kaydı kullanarak bir tür kaydettikten sonra TinyIoC için varsayılan davranış, tür her çözümlendiğinde veya bağımlılık mekanizması örnekleri diğer sınıflara eklediğinizde kayıtlı türün yeni bir örneğini oluşturmaktır. Bu senaryoda kapsayıcı, çözümlenen nesneye bir başvuru tutmaz. Ancak, arabirim kaydını kullanarak bir tür kaydederken TinyIoC için varsayılan davranış nesnenin ömrünü tekil olarak yönetmektir. Bu nedenle, kapsayıcı kapsam dahilindeyken örnek kapsam içinde kalır ve kapsayıcı kapsamın dışına çıktığında ve atık toplandığında veya kod kapsayıcıyı açıkça attığında atılır.
Varsayılan TinyIoC kayıt davranışı akıcı AsSingleton
ve AsMultiInstance
API yöntemleri kullanılarak geçersiz kılınabilir. Örneğin, AsSingleton
yöntemi yöntemiyle Register
kullanılabilir, böylece kapsayıcı yöntemi çağırırken Resolve
türün tek bir örneğini oluşturur veya döndürür. Aşağıdaki kod örneği TinyIoC'ye sınıfının tek bir örneğini oluşturma talimatını LoginViewModel
gösterir:
_container.Register<LoginViewModel>().AsSingleton();
Tür ilk kez LoginViewModel
çözümlendiğinde kapsayıcı yeni LoginViewModel
bir nesne oluşturur ve buna bir başvuru tutar. öğesinin LoginViewModel
sonraki çözümlerinde kapsayıcı, daha önce oluşturulmuş olan nesneye LoginViewModel
bir başvuru döndürür.
Not
Tekil olarak kaydedilen türler, kapsayıcı atıldığında atılır.
Özet
Bağımlılık ekleme, somut türlerin bu türlere bağlı koddan ayrıştırılmalarına olanak tanır. Genellikle, arabirimler ve soyut türler ile bu türleri uygulayan veya genişleten somut türler arasındaki kayıtların ve eşlemelerin listesini tutan bir kapsayıcı kullanır.
TinyIoC, iyi bilinen kapsayıcıların çoğuna kıyasla mobil platformlarda üstün performans sunan basit bir kapsayıcıdır. Gevşek bir şekilde bağlanmış uygulamalar oluşturulmasını kolaylaştırır ve tür eşlemelerini kaydetme, nesneleri çözümleme, nesne yaşam sürelerini yönetme ve bağımlı nesneleri çözümlediğinden nesne oluşturucularına ekleme yöntemleri de dahil olmak üzere bağımlılık ekleme kapsayıcılarında yaygın olarak bulunan tüm özellikleri sağlar.