Kod Flexability'i geliştirmek için Mvc'de Bağlanma Enjeksiyonunu Uygulayın

MVC'de Bağlanma Enjeksiyonuna Giriş

Model-View-Controller (MVC) deseni, sürekli olarak geri kalan sınıflara dönüşmek için sürekli baskı ile karşı karşıya kalır ve mevcut işlevselliği ihlal eder. Doğrudan veri taban bağlantılarına bağlı olarak, hizmetler anında beton depolayıcılar oluşturur - kendi işbirlikçileri inşa eden katı mimariler yaratır, bu işbirlikçiler dışsal adımlara geçişler yapılır ve mevcut işlevselliği bozabilir.

Bu makale, MVC çerçeveleriyle, dekoratörler ve yaşam yönetimi gibi gelişmiş kalıpların oluşturulmasına ve ortak tuzakların önlenmesine yönelik en iyi uygulamaları inceleyeceğiz. Hedef sizi ASP.NET Core'da somut uygulamalarınızla dondurabilecek pratik bilgilerle dondurmak ve MVC kodbase'inizi değiştirmek için uygun hale getirmektir.

Bağımlılık Enjeksiyonu Nedir?

Bağlanma Enjeksiyonu, bir nesnenin onları içsel olarak yaratmak yerine dış kaynaklardan bağımlılıklarını aldığı bir tasarım modelidir. Geleneksel nesne odaklı kodda, bir kontrol, yapı veya yöntemi içinde belirli bir havuz sınıfı anlık olarak verebilir:

public class UserController {
 private SqlUserRepository repository = new SqlUserRepository();
 // ...
}

Bu yaklaşım çiftleri doğrudan beton bir uygulamaya yönlendirmektedir. Farklı bir veri mağazasına geçiş yapmanız gerekiyorsa, giriş yapın veya bir caching katmanı uygulayın, kontrol cihazını değiştirmeniz gerekir. DI, kontrolör kendi yapılayıcı (veya bir setter) ve bir dış bileşene bağlı olduğunu ilan eder - sık sık sık bir IoC konteyneri olarak adlandırılır: Beton örnekleri:

public class UserController {
 private final UserRepository repository;
 public UserController(UserRepository repository) {
 this.repository = repository;
 }
 // ...
}

Şimdi kontrolör yalnızca uygulama ve yaşam döngüsünü kontrol eden nesnelere dokunmadan yenilebilir.Bu ilke, Kontrolün (IoC) felsefesinin daha geniş inversiyonunun bir ifadesidir.

Bağlanma Türleri

Bir sınıfa bağımlı olmanın üç yaygın yolu vardır. Her biri kullanım vakaları vardır, ancak kontraksiyon genellikle zorunlu bağımlılıklar için tercih edilir.

Yapıcı Enjeksiyon

Bağımlılıklar sınıf yapısı ile geçer. Bu, kontrol ve hizmetler için varsayılan model olarak yapılabilmesi için bağlıdır, nesnenin tam olarak başlangıçlı olmasını sağlar ve taklit edilebilirliği destekler. Çoğu modern çerçeveler kontrol ve hizmetler için varsayılan model olarak yapılamaya güvenir.

public class OrderController {
 private readonly IOrderService _orderService;
 public OrderController(IOrderService orderService) {
 _orderService = orderService;
 }
}

Setter / Emlak Enjeksiyonu

Bağımlılık, nesne inşa edildikten sonra kamu setleri veya özellikleri ile belirlenir. Bu model, varsayılan bir uygulamanın sağlanabileceği veya anından sonra bir bağımlılık yeniden yapılandırmanız gerektiğinde, ayarlanmamış herhangi bir şekilde kullanılmadığı takdirde, uygun olmayan işbirlikçiler için en iyi şekilde rezerve edilir.

public class NotificationController {
 public ILogger Logger { get; set; }
 // Default logger if none injected
 public NotificationController() {
 Logger = new NullLogger();
 }
}

Interface Enjeksiyon

Sınıf, bir bağımlılık almak için bir yöntem tanımlayan bir arayüz uygular. IoC konteyneri, çalıştır zamanında bu yöntemin daha az yaygın olduğunu arar. Bu yaklaşım MVC çerçevelerinde daha az yaygındır, ancak birden çok bağımlılıkların eklentileri ile uyumlu bir şekilde enjekte edilmesi gerektiği bazı gelişmiş senaryolarda görünür.

public interface IEmailServiceAware {
 void SetEmailService(IEmailService service);
}
public class AccountController : Controller, IEmailServiceAware {
 private IEmailService _emailService;
 public void SetEmailService(IEmailService service) {
 _emailService = service;
 }
}

Kontrol konteynerlerinin Inversiyonunun Rolü

Örneğin, bir fabrika veya basit bir hizmet taşıyıcısı kullanarak - üretim uygulamaları bir IoC konteynerinden faydalanır. Bir IoC konteyneri, Java'da kayıt yaptırmadan sorumlu bir kütüphanedir, bağımlılıkları yönetir ve nesne yaşamlarını yönetir.Bu yüzden geliştiricilerin bunları manuel olarak anlık nesnelere sahip olması ve katmanları aracılığıyla geçmesi gerekir.

Konteyner, ilk olarak bir soyutlamadan (yüzlü veya soyut sınıf) bir beton uygulama için bir harita kaydetti. Sonra, bir kontrol talep edildiğinde, konteyner denetimin yapılabilmesini denetim eder ve her bağımlılık için kayıtlı uygulamaları görünür ve bu uygulamaları başka bağımlılıkları tekrar çözer.

Konteynerler ayrıca nesnelerin ömrünü de yönetiyor - atmadan önce ne kadar uzun bir örnek hayatta tutuluyor. Üç en yaygın yaşam:

Doğru yaşam seçimi, sabit hataları, sabit veriler veya istenmeyen kaynak paylaşımı gibi engeller.Incorrect yaşamları ayrıca hafıza sızıntılarına veya thread güvenli sorunlara neden olabilir, böylece her bir konteynerin semantikunu anlamak önemlidir.

MVC Architecture'da Bağlanmanın Faydaları

Bir MVC uygulaması içinde DI uygulamak, kodbase'i birkaç ölçülebilir şekilde dönüştürür:

Çeşitli MVC Framework'lerde DI'yı uygulama

DI kavramı dilbilimci olmasına rağmen, her MVC çerçevesi kendi konteyner ve kongrelerini ortaya çıkarır. Aşağıda üç popüler ekosistemden somut örnekler vardır.

ASP.NET Core (C#)

ASP.NET Core, inşa edilmiş DI konteynerine sahiptir ve bunlar, İLFLT:8'de yapılandırılır. Hizmetler, koleksiyonun içinde kaydedilir ve kontroller otomatik olarak yapılabilmesine bağlı olarak bağımlılık alır.

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
builder.Services.AddTransient<IEmailService, SmtpEmailService>();
builder.Services.AddSingleton<ILogger, ConsoleLogger>();

builder.Services.AddControllersWithViews();

var app = builder.Build();
// ... middleware configuration
app.Run();

Kontrolörde, sadece bağımlılık ilan edersiniz:

public class OrderController : Controller {
 private readonly IOrderRepository _repository;
 private readonly IEmailService _emailService;
 public OrderController(IOrderRepository repository, IEmailService emailService) {
 _repository = repository;
 _emailService = emailService;
 }
 public IActionResult Index() {
 var orders = _repository.GetAll();
 return View(orders);
 }
}

ASP.NET Core'un konteyneri ayrıca açık jeneriklerin, fabrika yöntemlerinin ve dekoratörlerin açık kayıtlarını da destekler. Seçmeli bağımlılıklar için, [[Ücretsizlikler için, [[Ücretsizlikler için, kalıp veya setter enjeksiyonu ile 03:9) özelliği kullanabilirsiniz.

Bahar MVC (Java)

Bahar IoC konteyneri en olgun DI çerçevelerinden biridir. Bir Bahar MVC uygulamasında, stereotiplerle ([DÜT: 16) bir notaksiyon veya enjeksiyon alanı ile enjekte edilir.

@Controller
public class ProductController {
 private final ProductService productService;
 // Constructor injection – Spring automatically wires the ProductService
 public ProductController(ProductService productService) {
 this.productService = productService;
 }
 @GetMapping("/products")
 public String listProducts(Model model) {
 model.addAttribute("products", productService.findAll());
 return "productList";
 }
}

Kurulum genellikle Java annotasyonları veya XML. Bean kapsamı ile yapılır (singleton, prototip, istek, oturum) işlem yönetimi veya güvenlik gibi endişeleri uygulamak için. Spring ayrıca yöntem enjeksiyonu, yaşam döngüsü çağrıları gibi gelişmiş özellikler sunar ve AOP entegrasyonu ile birlikte DI ile birlikte olabilir.

Laravel (PHP)

Laravel, otomatik karar, bağlayıcı arabirimleri uygulama için destekleyen güçlü bir hizmet konteynerini kullanır ve bağlamsal bağlayıcı. Laravel'in MVC yapısı, kontroller, orta sınıflar ve hizmet sağlayıcıları aracılığıyla bağımlılık teşvik eder.

// In a ServiceProvider's register() method
$this->app->bind(PaymentGatewayInterface::class, StripeGateway::class);
$this->app->singleton(LoggerInterface::class, FileLogger::class);

Bir kontrolörde, inşaat veya bir yöntemdeki bağımlılıktan kaçınıyorsunuz. Laravel'in konteyneri otomatik olarak çözüyor:

class InvoiceController extends Controller {
 protected $paymentGateway;
 public function __construct(PaymentGatewayInterface $paymentGateway) {
 $this->paymentGateway = $paymentGateway;
 }
 public function pay(Invoice $invoice) {
 $this->paymentGateway->charge($invoice);
 // ...
 }
}

Laravel ayrıca kontrol yöntemlerinde otomatik enjeksiyonu destekliyor (kırın yönteminin çözümüyle) ve konteynere bağlı örneklerin taşıyıcı olarak hareket eden cepheler sağlar. Ancak, en iyi uygulama, doğrudan test edilebilirliği sağlamak için cephelere güvenmekten ziyade arayüzleri enjekte eder.

MVC için Gelişmiş DI Desenleri

Temel DI'nın sağlam bir anlayışına sahipseniz, tekrarlanan mimari sorunları çözmek için daha sofistike desenlerden yararlanabilirsiniz.

Dekoratör Desen

Dekorasyon modeli, kodu değiştirmeden mevcut bir hizmete davranış eklenize olanak sağlar. Bir IoC konteyneriyle, orijinal uygulamayı sarmalayan bir dekorasyonatör kayıt olabilirsiniz. Örneğin, bir ürün arama hizmetine neden eklemek isteyebilirsiniz:

services.AddScoped<IProductRepository, ProductRepository>();
services.Decorate<IProductRepository, CachedProductRepository>();

[FONT=FONT] gerçek repository'yi inşaat veya enjeksiyon ve delegeler ile bir caching katmanı ekleyerek alır. Bu, gerçek veri erişim kodu saf ve test edilebilir tutar.

Interception / AOP

Bazı konteynerler, özellikle Castle Windsor (ASP.NET) ve Spring AOP, kayıtlı hizmetler üzerinde yöntem aramalarını engellemenize izin verir. Interceptors, log, performans izleme, izin kontrolü veya işlem yapmadan iş mantığına giriş yapın. Interception, DI ile el elemanları.

Lifetime Scopes and Disposal

Örneğin, nesneler yaratıldığında ve yok edildiğinde anlamak önemlidir. Örneğin, bir veritabanı bağlamı ([Dönetici Framework’te :23) genellikle tekton olarak kayıtlı olmalıdır, birden fazla eş zamanlı istek aynı bağlamı paylaşabilir, yolsuzluk veya durgun verilere yol açabilir.

Ayrıca, konteynerin düzgün bir şekilde uygulama kodu altında bulunan nesnelerden tasarruf etmesini sağlar. Çoğu konteyner otomatik olarak talep sonunda kapsamıştırılır ve geçici örnekler talep edilen konteynerler için, ancak yönetim dışındaki konteynerden nesneleri manuel olarak çözmesi, sızıntılara yol açabilir. Ortak bir kılavuz: Uygulama kodu içindeki konteynerden doğrudan çözümle kalmaz; bunun yerine, inşaatçıklama işlemine izin verir.

Ortak Pitfalls ve Them'dan Nasıl Kaçırmak

En iyi niyetlerle bile, DI, yanlış yorumlanmış olsa sorunları ortaya çıkarabilir. Bu tuzakların farkındalığı temiz bir mimariye yardımcı olur.

MVC'de Bağlanma Enjeksiyonu için En İyi Uygulamalar

Ortak hatalardan kaçınırken DI faydalarını maksimize etmek, bu yönergeleri takip etmek:

Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç Sonuç

Bağlanma Enjeksiyonu sadece bir trendsel model değildir; MVC uygulamalarının kablo ve yaşam yönetimi olmadan büyümesini sağlayan temel bir uygulamadır.Rekalatıcı kontrolörler, hizmetler ve veri erişim katmanları beton uygulamalarından, yeni gereksinimlerin adapte olma yeteneği kazanırsınız, teknolojiler ve kolay bir şekilde test yazabilirsiniz. Modern IoC konteynerleri, iş mantığına nesne oluşturmadan ziyade odaklanmanıza izin verir.

ASP.NET Core, Spring MVC veya Laravel'yı kullanıyorsanız, prensipler aynı kalır: Dıştan soyut, ve kompozisyon kök merkezileşmiş tutmak yerine, tek bir kontrole yeniden başlamak, sonra yavaş yavaş tüm uygulama için bir IoC konteyneri ortaya koyar.

Daha fazla okuma için, çerçevenizin DI konteynerinin resmi belgelerini keşfedin veya Martin Fowler'in makalesini [[Düzgöçreleri ve Bağımlılık Enjeksiyonu[Döneticileri) ile ilgili klasik kaynakları danışmak (Düzük)[Düzüğün hizmet konteyneri[Düzüğün hizmet konteyneri[Döneticileri ve örnekleri)