Aurelia bağımlılık enjeksiyonu ile kullanılmak üzere global TypeScript yapılandırmasını (arayüz) tanımlayın
Aurelia'da, aynı yapılandırmaya bağımlı birkaç sınıfım var. IoC/DI kullanarak, bu yapılandırmanın bir yapıcı parametresi olarak sağlanması doğal görünüyor. Örneğin:
@autoinject
export class CustomerService {
constructor(config: IRemoteServiceConfig) {
}
}
@autoinject
export class GummyBearService {
constructor(config: IRemoteServiceConfig) {
}
}
En basit örnekte, IRemoteServiceConfig şöyle görünebilir (kısalık için diğer şeyler çıkarıldı):
export IRemoteServiceConfig {
endpoint: string;
apiKey?: string;
// etc. several other settings
}
Yapılandırmanın constructor'a enjekte edilmesi test için idealdir ve her sınıfta konfigürasyonları ve ayarları okumamı gerektirmez.
Hizmetler aynı yapılandırmaya bağlıdır, bunu uygulamamda başlangıçta - bir kez - tanımlamak istiyorum.
Aurelia belgelerinde bağımlılık enjeksiyonu ile ilgili okurken, bu amaç için registerInstance(), registerResolver() ve registerSingleton() gibi birkaç yöntem olduğunu görüyorum. Belgelerde bunu nasıl ve nerede tanımlayacağımız konusunda bazı bağlam eksikliği var.
Başlangıç rutinimdeki configure() bölümünde aşağıdakine benzer bir şeyle başladım:
// register a static config; for brevity these are hardcoded settings
// but could come from anywhere
container.registerSingleton(IRemoteServiceConfig, () => {
return <IRemoteServiceConfig> {
endpoint: 'http://foo.com/api/v23/',
apiKey: 'abc'
}
});
Hiçbir şey algılamıyor gibi görünüyor (hata yok). Ama bu, konteyneri nasıl başlatacağımı bilmememden de kaynaklanıyor olabilir.
Sorum: IRemoteServiceConfig'i Aurelia'da nasıl ve nerede tanımlayabilirim, eğer tanımlanabiliyorsa, böylece DI servisler için devreye girdiğinde otomatik olarak benim (sabitlenmiş) yapılandırmamı alır?
Bu SO sorusunda "arayüzlerle çalışamaz çünkü TypeScript bunları çalışma zamanında derler." ifadesinin geçtiğini unutmayın. Soru ayrıca +2 yıl önce ve hem Aurelia hem de TypeScript'te birçok şey değişti. Bu durum hala geçerlidir veya geçerli değildir, aynı soru bir arayüz yerine bir sınıf örneği için de geçerlidir.
Ayrıca, appsettings’i bir yapılandırma dosyasında depolamak için uygun görünen aurelia-configuration gibi kütüphanelerin farkında olduğumu lütfen unutmayın (ve bunlar gayet iyi çalışıyor). Bu, verilen örnek için daha mantıklı olurdu. Ancak soru tamamen, bir arayüzü veya bir sınıfın belirli bir örneğini Aurelia DI tarafından çözülmek üzere nasıl tanımlayabileceğim ile ilgilidir.
Cevap #1
@estus tarafından verilen cevap doğru ve ben bunu bir cevap olarak işaretledim. Bununla birlikte, bunu düzgün çalıştırmak için bazı ek sorunlarla karşılaştım. Bunu belirtmek için, aşağıda ek detaylarla bir cevap yazmak için zaman ayırdım, umarım gelecekte başkalarına da yardımcı olur.
1.) Bir arayüz değil, sınıf kullanın
Kabul edilen cevapta belirtildiği gibi, arayüzleri kullanamazsınız - bir sınıf olmalıdır.
2.) aurelia.container aracılığıyla global container örneğine erişin
Dokümantasyon, container örneğine nasıl erişileceğini belirtmiyor. Ancak, configure() işlemi içinde varsayılan/global container'a aurelia.container üzerinden doğrudan erişebilirsiniz, şöyle:
aurelia.container.registerSingleton(RemoteServiceConfig, () => {
var config = new RemoteServiceConfig();
config.endpoint = 'http://foo.com/api/v23/',
config.apiKey = 'abc'
});
Bir Container() nesnesinin yeni bir örneğini başlatma ve bunu bir şekilde configure() işlemi içinde enjekte etmeye çalışma hatasını yaptım. Yapmamalıydım :)
3.) Sınıflarınızı farklı dosyalara ayırın
Bu saçma görünebilir ama önemlidir: Sınıflar aynı dosyada olamaz, aksi takdirde aşağıdaki hatayı alırsınız:
anahtar/değer null veya tanımsız olamaz. DI ile var olmayan bir şeyi enjekte/ kaydetmeye mi çalışıyorsunuz?
Orijinal sorunun amacı için, tüm sınıfları aynı app.ts dosyasında oluşturdum. Ve bu basitçe işe yaramıyor gibi görünüyor.
Tüm bunlar söylenmişken, tam uygulama şimdi şöyle görünüyor ve çalışıyor:
main.ts
import { Aurelia } from 'aurelia-framework'
import { RemoteServiceConfig } from './app';
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.feature('resources');
aurelia.container.registerSingleton(RemoteServiceConfig, () => {
var config = new RemoteServiceConfig();
config.endpoint = 'http://foo.com/api/v23/',
config.apiKey = 'abc'
});
aurelia.start().then(() => aurelia.setRoot());
}
app.ts
import { autoinject } from 'aurelia-dependency-injection';
// note: classes below should be 3 different files!
@autoinject
export class App {
constructor(private service: CustomerService) {
}
}
@autoinject
export class CustomerService {
constructor(private config: RemoteServiceConfig) {
}
}
export class RemoteServiceConfig {
public endpoint: string;
public apiKey?: string;
}
Cevap #2
Arayüzler çalışma zamanında mevcut değildir, hangi TypeScript sürümü kullanılırsa kullanılsın.
Hem bir arayüz hem de DI tokeni olarak kullanılabilmesi için, IRemoteServiceConfig bir sınıf olmalıdır:
export abstract class IRemoteServiceConfig { ... }
