Pertanyaan Castle Windsor Dependency Resolver untuk MVC 3


Karena implementasi IoC / DI dalam MVC 3 kemungkinan besar dalam bentuk finalnya di RC, saya mencari implementasi terbaru dari DependencyResolver, IControllerActivator dan IViewPageActivator menggunakan Caste Windsor. Apakah ada contoh di luar sana yang telah diperbarui untuk MVC 3 RC?

EDIT # 1 Menerapkan resolver ketergantungan Windsor memang sepele, tetapi masih ada sesuatu yang hilang. Bertentangan dengan contoh Jeffin Putin's Ninject (di bawah), tampak bahwa itu tidak sesederhana itu dengan Windsor. Setelah mengatur resolver dependensi seperti itu,

DependencyResolver.SetResolver(new WindsorDependencyResolver(container)); 

Windsor melempar ComponentNotFoundException. Saya perlu menyediakan implementasi untuk IControllerFactory dan IControllerActivator. Karena DefaultControllerFactory adalah DependencyResolver yang sadar, ini dapat diselesaikan sebagai berikut:

Component.For<IControllerFactory >().ImplementedBy<DefaultControllerFactory>()
Component.For<IControllerActivator >().ImplementedBy<WindsorControllerActivator>(),

WindsorControllerActivator juga sepele. Namun, ini mengarah ke ComponentNotFoundException lain untuk IViewPageActivator.

Ini membuat saya percaya bahwa saya kehilangan sesuatu. Tidak ada cara ini harus lebih rumit daripada mengimplementasikan pabrik pengontrol dan memanggil ControllerBuilder.Current.SetControllerFactory MVC 2.0-style.

EDIT # 2 Saya merindukan detail halus tetapi penting bahwa Penyelesai Ketergantungan perlu mengembalikan nol ketika layanan tidak dapat ditemukan. Implementasinya adalah sebagai berikut:

public class WindsorDependencyResolver : IDependencyResolver
{
    private readonly IWindsorContainer container;

    public WindsorDependencyResolver(IWindsorContainer container)
    {
        this.container = container;
    }

    public object GetService(Type serviceType)
    {
        return container.Kernel.HasComponent(serviceType) ? container.Resolve(serviceType) : null;
    }

  public IEnumerable<object> GetServices(Type serviceType)
    {
        return container.Kernel.HasComponent(serviceType) ? container.ResolveAll(serviceType).Cast<object>() : new object[]{};
    }
}

EDIT # 3

Menanggapi sebuah pertanyaan di komentar. Jika Anda menemukan bahwa Anda memerlukan IControllerActivator Anda sendiri, di sini implementasi sederhana untuk Windsor:

public class WindsorControllerActivator : IControllerActivator
{
    private readonly IWindsorContainer container;

    public WindsorControllerActivator(IWindsorContainer container)
    {
        this.container = container;
    }

    public IController Create(RequestContext requestContext, Type controllerType)
    {
        return (IController)container.GetService(controllerType);
    }
}

}

Sekali lagi, ini TIDAK diperlukan untuk mendapatkan DI dasar bekerja dengan Windsor dan resolver ketergantungan MVC3.

EDIT # 4 Berdasarkan beberapa penelitian dan umpan balik lebih lanjut, tampaknya penerapan pabrik pengendali tradisional adalah pendekatan terbaik untuk Windsor dan MVC3. Yang menjadi perhatian adalah bahwa antarmuka IDependencyResolver tidak memiliki metode rilis, yang dapat menyebabkan kebocoran memori dengan Windsor tidak membuang komponennya. Ini mungkin tidak akan menjadi masalah jika semua dependensi Anda diselesaikan dengan siklus hidup PerWebRequest, tetapi masih lebih baik untuk tidak mengambil risiko. Berikut adalah implementasi dasar dari pabrik pengendali Windsor untuk MVC3.

public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IWindsorContainer container;

    public WindsorControllerFactory(IWindsorContainer container)
    {
        this.container = container;
    }

    public override void ReleaseController(IController controller)
    {
        container.Kernel.ReleaseComponent(controller);
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controllerComponentName = controllerName + "Controller";
        return container.Kernel.Resolve<IController>(controllerComponentName);
    }
}

EDIT # 5 Jika Anda menggunakan area MVC, implementasi di atas tidak akan berfungsi untuk Anda. Anda harus mendaftarkan setiap pengontrol berdasarkan nama lengkapnya, dan mengganti GetControllerInstance daripada CreateController:

 protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType != null)
        {
            return (IController)container.Kernel.Resolve(controllerType);
        }
        return null;
    }

32
2017-11-10 03:02


asal


Jawaban:


Antarmuka tidak berubah sejak rilis beta, jadi semua implementasi untuk berbagai kerangka kerja harus tetap berfungsi. Dan kenyataannya, itu tidak rumit dari antarmuka ... Anda harus dapat menggulung sendiri tanpa banyak kerumitan. Misalnya, saya melakukan ini untuk Ninject:

public class NinjectDependencyResolver : IDependencyResolver
{
    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    private readonly IKernel _kernel;

    public object GetService(Type serviceType)
    {
        return _kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _kernel.GetAll(serviceType);
    }
}

Kemudian pasang kabel di global.asax seperti ini:

    private static IKernel _kernel;
    public IKernel Kernel
    {
        get { return _kernel; }
    }

    public void Application_Start()
    {
        _kernel = new StandardKernel(new CoreInjectionModule());
        DependencyResolver.SetResolver(new NinjectDependencyResolver(Kernel));
        ...
    }

Ingat, Anda mendapatkan semua jenis barang gratis pada saat itu, termasuk DI untuk pengontrol, pabrik pengontrol, filter tindakan, dan melihat kelas dasar.

EDIT: Untuk menjadi jelas, saya tidak yakin apa "aktivator" Anda, tetapi Anda mungkin tidak membutuhkannya. Antarmuka IDependencyResolver menangani pembaruan pengendali dan tampilan secara otomatis.


10
2017-11-10 04:25



Antarmuka MVC3 IDependencyResolver memiliki masalah besar: tidak ada metode rilis. Ini berarti ada kebocoran memori potensial jika Anda akan menggunakannya dengan Windsor. Lihat posting blog saya tentang ini di sini:

http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html


24
2018-02-03 17:06



MVCContrib saat ini adalah sumber otoritatif untuk integrasi IoC-MVC. Saat ini, cabang MVC3 hanya mencakup pabrik controller dan implementasi IDependencyResolver (dan beberapa hal lainnya). Saya merekomendasikan forking repositori dan mengimplementasikan titik ekstensi yang hilang (seharusnya tidak terlalu sulit), kemudian mengirim tim permintaan tarik.


2
2017-11-10 04:16