Injeksi Ketergantungan Di Perpustakaan Kelas

Memiliki solusi dengan dua proyek Saya mengalami masalah DI. Solusinya terdiri dari perpustakaan kelas dan aplikasi WebApi2 (yang menggunakan perpustakaan kelas dan mengekspos api).

Saya telah mendefinisikan Autofac.module di perpustakaan kelas yang mengatur semua DI dalam proyek.

Dalam proyek WebApi2 saya membuat wadah DI (menggunakan Autofac.WebApi2) dan memuat modul dari perpustakaan kelas. Sekarang ketika pengontrol api di proyek WepApi2 meminta layanan di perpustakaan kelas, mereka dibuat dengan semua dependensinya, semuanya berfungsi dengan baik!

Masalahnya adalah saya sekarang di perpustakaan kelas perlu membuat instance beberapa kelas dari string (yang akhirnya berasal dari DB), sejauh yang saya tahu satu-satunya cara untuk melakukan ini adalah dengan menggunakan refleksi, jadi saya melakukan seperti ini:

var ruleType = Type.GetType(rule.RuleImplementation.Implementation);
var rule = (IRule)Activator.CreateInstance(ruleType,param1,param2);

Masalahnya adalah kelas yang mengimplementasikan antarmuka IRule juga memiliki ketergantungan yang perlu diselesaikan, dan inilah yang membuat saya menggedor-gedor keyboard saya untuk sementara waktu sekarang.

Apakah mungkin menggunakan refleksi dan autoFac secara bersamaan untuk membuat instance objek? Saya masih harus bisa meneruskan parameter saya ke objek juga.

... Atau adakah cara untuk mengakses wadah (yang dibuat di rakitan webApi2) dan menggunakannya untuk mengatasinya? Saya kira ini akan menjadi semacam pola layanan yang saya yakini dianggap sebagai anti pola.

Bagaimana cara melanjutkannya? Segala masukan sangat kami hargai.


person iCediCe    schedule 02.12.2016    source sumber


Jawaban (2)


Membuat komponen Anda menggunakan Activator.CreateInstance adalah ide yang buruk, karena pada dasarnya itu berarti Anda mengimplementasikan ulang logika yang dilakukan container untuk Anda, namun tanpa fitur dan penjaga keamanan yang disediakan oleh perpustakaan DI.

Saya telah mendefinisikan Autofac.module di perpustakaan kelas yang mengatur semua DI dalam proyek.

Di sinilah letak sumber masalah Anda. Seharusnya hanya ada satu tempat dalam aplikasi di mana grafik objek disusun (dan didaftarkan) dan ini adalah Akar Komposisi. Akar Komposisi ini dapat dilihat sebagai lapisan terpisah yang terletak di atas lapisan presentasi Anda (API Web), meskipun Akar Komposisi (lapisan) dan Lapisan Presentasi cukup umum berada dalam proyek yang sama.

Melakukan hal ini akan menghilangkan masalah, karena di dalam root komposisi Anda, Anda sudah memiliki akses ke container.

Solusi yang baik untuk memungkinkan aturan dibuat menggunakan beberapa definisi yang berasal dari database adalah dengan mendefinisikan abstraksi IRuleActivator. Abstraksi ini dapat ditentukan di perpustakaan Anda dan diimplementasikan di dalam root komposisi. Hal ini memungkinkan implementasi untuk membungkus container, sementara perpustakaan tetap tidak menyadari keberadaan container tersebut:

// Defined in the library
public interface IRuleActivator
{
    IRule GetRule(RuleData rule);
}

// Defined in the Compostion Root
public sealed class AutofacRuleActivator : IRuleActivator
{
    private readonly IComponentContext context;
    public AutofacRuleActivator(IComponentContext context) {
        this.context = context;
    }

    public IRule GetRule(RuleData rule) {
        Type ruleType = Type.GetType(rule.RuleImplementation.Implementation);
        return (IRule)this.context.Resolve(ruleType);
    }
}
person Steven    schedule 02.12.2016

Anda dapat membuat pabrik untuk pembuatan IRule:

public IRuleFactory
{
   IRule CreateRule(params);
}

Untuk parameter saya akan menggunakan beberapa jenis IParamsProviders yang dapat disuntikkan kemudian ke dalam implementasi IRuleFactory, RuleImpl hanyalah implementasi konstruksi objek Anda, dapat menjadi refleksi juga:

public class RuleFactory : IRuleFactory
{
    public RuleFactory(IParamsProvider provider)
    {
        ...
    }

    public IRule CreateRule()
    {
        return new RuleImpl(provider.Param1, provider.Param2);
    }
}

Daftarkan antarmuka ini ke Ioc dan masukkan ke dalam pengendali layanan.

person Johnny    schedule 02.12.2016
comment
Saya suka solusi ini. Sejauh yang saya lihat, satu-satunya kelemahan adalah saya harus memasukkan semua aturan ke dalam layanan saya terlepas dari apakah aturan tersebut diperlukan atau tidak, karena saya pertama kali mengetahuinya saat runtime ketika saya menanyakan DB. - person iCediCe; 05.12.2016