Bağımlılık Enjeksiyonu

Servis Çözümleme

ServiceProvider.get ve getAsync, bileşende getService, FromService, inject, deps ve useApplication.

Servis çözümleme

Kayıtlı bir servis sağlayıcıdan istenir. Bileşende getService ya da FromService, servis kurulurken inject ya da deps, bunların dışında sağlayıcının kendisi (app.provider) kullanılır.

ServiceProvider.get

const provider = app.provider;
const notes = provider.get(NotesService);
const provider = app.provider;
const notes = provider.get(NotesService);

Router bir rota bileşenini, sağlayıcıda kayıtlıysa (add* ya da @Injectable) sağlayıcıdan çözer, kayıtlı değilse doğrudan kurar. Kayıtlı bir bileşen çözülemezse (eksik bağımlılık, döngü, yapıcı hatası) gezinme MJX304 ile hata verir, asıl hata cause'da taşınır ve fallbacks.error gösterilir.

get senkrondur ve async fabrika ya da Promise ile kaydedilmiş bir servis için hata (MJX402) fırlatır; onları await provider.getAsync(token) ile çözümleyin. provider.createScope(ad?) yeni bir alt kapsam üretir; scoped servisler kapsam başına tek örnektir.

Uygulama örneğine erişimi olmayan bir yerden (bir yardımcı modül, rota kancası) çalışan uygulamanın sağlayıcısına Application.main.provider ile ulaşılır:

const notes = Application.main.provider.get(NotesService);
const notes = Application.main.provider.get(NotesService);

Bileşenden getService

getService, en yakın sağlayıcıyı bulup token'ı çözümler; bulunamazsa ya da çözümleme hata verirse null döner (geliştirme modunda MJX407/MJX408 uyarısı yazılır). Örnekte not listesi başlığı, kurulurken toplam not sayısını title özniteliğine yazar:

const notes = this.getService(NotesService);
if (notes) this.attr.add({ title: `${notes.count("notes")} not` });
const notes = head.getService(NotesService);
if (notes) head.attr.add({ title: `${notes.count("notes")} not` });
const notes = this.getService(NotesService);
if (notes) this.attr.add({ title: `${notes.count("notes")} not` });
const notes = head.getService(NotesService);
if (notes) head.attr.add({ title: `${notes.count("notes")} not` });

Sınıf ve Options bileşeninde getService bileşenin kendisi üzerindedir; bu satırlar bir kancada (onConfig, onConfigured) ya da alan başlatıcısında this ile yazılır.

Fonksiyon bileşeninde getService bileşenin kendisi üzerindedir (örnekte head): JSX'te kökün onConfig kancasına ya da ref'ine gelen bileşen, JSX'siz yazımda kökü kuran motifComponent fonksiyonunun aldığı bileşen. Bileşen elde değilken aynı işi FromService görür.

getService ve FromService servis kayıtlı değilse null döner; inject, provider.get ve provider.getAsync bulamazsa fırlatır.

Sınıf token'ı verildiğinde dönüş tipi o sınıftır; kurucusu parametre alan, soyut ya da protected kurucusu olan sınıflar da buna dahildir. getService ve FromService null olabilen tip (T | null), inject, provider.get ve provider.getAsync null olmayan tip verir. Generic'i açıkça yazmak (getService<NotesService>(NotesService)) aynı tipi verir; sınıfı bir arayüzle tiplemek için kullanılabilir: FromService<NoteStore>(NotesService). Dizge ya da sembol token'da tip generic'le verilir: getService<{ apiUrl: string }>("config").

FromService yardımcısı

Herhangi bir yerde (bileşen dışında da) hızlı çözümleme için:

import { FromService } from "@motifx/core";
const notes = FromService(NotesService);   // çözümlenemezse null
import { FromService } from "@motifx/core";
const notes = FromService(NotesService);   // çözümlenemezse null

Servis kayıtlı değilse, döngüsel bağımlılık varsa ya da yapıcı hata fırlatırsa null döner; geliştirme modunda asıl hatayla birlikte MJX414 uyarısı yazılır. scoped bir servis için güncel gezinmenin örneğine giden handle'ı verir.

inject(token) — bağımlılık alma

inject, sağlayıcı bir sınıfı kurarken o sınıfın alan başlatıcılarında ve yapıcısında, ya da sağlayıcı bir useFactory fabrikasını çağırırken fabrikanın içinde çağrılır. Bağımlılığı sınıfı kuran sağlayıcıdan çözer: scoped bir servis, onu isteyen rota kapsamının örneğidir. Dönüş tipi token'dan gelir.

@Injectable()
export class SearchIndex {
  private notes = inject(NotesService);
  private config = inject<{ apiUrl: string }>("config");
  private readonly size: number;

  constructor() {
    this.size = this.notes.count("notes");   // yapıcıda da kullanılabilir
  }
}
@Injectable()
export class SearchIndex {
  notes = inject(NotesService);
  config = inject("config");
  size;

  constructor() {
    this.size = this.notes.count("notes");   // yapıcıda da kullanılabilir
  }
}

inject yalnız kurulum anında çalışır. Bir metodun içinde, setTimeout geri çağrısında ya da sınıf elle new SearchIndex() ile kurulduğunda MJX409 hatası fırlatır. Kayıtlı olmayan token MJX401, döngüsel bağımlılık MJX404 verir. inject senkrondur; getAsync gerektiren async kayıtları deps ya da getAsync ile alın.

Sınıf ve Options bileşeninde bağımlılık için this.getService(token) kullanılır.

Fonksiyon bileşeninde bağımlılık için FromService(token) kullanılır.

deps — yapıcı parametreleri

Bağımlılıklar yapıcıya parametre olarak da verilebilir. deps dizisindeki token'lar sırayla çözümlenir ve yapıcıya aynı sırada geçirilir:

@Injectable({ deps: [NotesService, "config"] })
export class SearchIndex {
  constructor(private notes: NotesService, private config: { apiUrl: string }) {}
}
@Injectable({ deps: [NotesService, "config"] })
export class SearchIndex {
  constructor(notes, config) {
    this.notes = notes;
    this.config = config;
  }
}

Sıra TypeScript tarafından denetlenmez; deps ile yapıcı parametreleri aynı sırada yazılmalıdır. Bu biçimde sınıf testte sahte bağımlılıklarla elle kurulabilir: new SearchIndex(sahteNotes, { apiUrl: "/test" }).

useApplication kancası

useApplication() çalışan uygulamayı, sağlayıcısını ve router'ı tek nesnede verir; attach(...bileşenler) bileşenleri uygulama kabuğuna ekler:

import { useApplication } from "@motifx/core";

const { application, services, router, attach } = useApplication();
const notes = services.get(NotesService);
import { useApplication } from "@motifx/core";

const { application, services, router, attach } = useApplication();
const notes = services.get(NotesService);

Sonraki adım

Servislerin ne zaman ve nasıl serbest bırakıldığını öğrenmek için Servislerin Serbest Bırakılması bölümüne geçin.