Injeksi Ketergantungan ASP.NET MVC 3 - Pengontrol, Tampilan & Filter Tindakan

Saya mencoba agar injeksi ketergantungan berfungsi di aplikasi ASP.NET MVC 3 menggunakan Microsoft Unity. Pertama saya telah mengimplementasikan IDependencyResolver saya sendiri dan mengaktifkannya di file Global.asax saya seperti:

DependencyResolver.SetResolver(new UnityDependencyResolver(container));

Saya menemukan bahwa saya tidak perlu melakukan apa pun agar injeksi pengontrol (melalui atribut konstruktor dan [Ketergantungan]) berfungsi. Dengan mesin tampilan default, saya juga menemukan saya bisa membuat atribut [Ketergantungan] berfungsi dalam tampilan standar tetapi tidak pada tampilan Tata Letak. Apakah mungkin untuk membuat ini berfungsi untuk Tampilan Tata Letak juga?

Namun saya telah menerapkan mesin tampilan saya sendiri yang mewarisi dari VirtualPathProviderViewEngine yang menggantikan metode CreateView/CreatePartialView dan mengembalikan tampilan kustom saya sendiri (mengimplementasikan IView). Lihat metode Render pada tampilan kustom di bawah ini:

public void Render(ViewContext viewContext, TextWriter writer) {
    var webViewPage = DependencyResolver.Current.GetService(_type) as WebViewPage;
    //var webViewPage = Activator.CreateInstance(_type) as WebViewPage;

    if (webViewPage == null)
        throw new InvalidOperationException("Invalid view type");

    webViewPage.VirtualPath = _virtualPath;
    webViewPage.ViewContext = viewContext;
    webViewPage.ViewData = viewContext.ViewData;
    webViewPage.InitHelpers();

    WebPageRenderingBase startPage = null;

    if (_runViewStartPages)
        startPage = StartPage.GetStartPage(webViewPage, "_ViewStart", _viewStartFileExtensions);

    var pageContext = new WebPageContext(viewContext.HttpContext, webViewPage, null);
    webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);
}

Dengan baris yang dikomentari saya benar-benar kehilangan injeksi ketergantungan dalam pandangan saya jadi saya mengubahnya ke baris di atas yang lagi-lagi berfungsi dengan baik untuk tampilan standar tetapi tidak untuk tampilan Tata Letak. Saya akan sangat menghargai jika Anda dapat menunjukkan kepada saya bagaimana hal di atas dapat dimodifikasi agar berfungsi untuk tampilan Tata Letak juga?

Akhirnya saya mencoba agar injeksi filter tindakan berfungsi juga. Saya menemukan dua kasus berbeda:

  1. Terapkan filter ke tindakan melalui atribut.

  2. Mendefinisikannya sebagai filter global, misalnya:

    GlobalFilters.Filters.Add(TesAttribute baru());

Tampaknya tidak ada yang menggunakan pemecah ketergantungan. Oleh karena itu saya perlu melakukan beberapa pekerjaan ekstra. Harap perbaiki saya jika ada cara yang lebih baik. Untuk mengaktifkan skenario pertama saya melakukan hal berikut:

public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
    private IUnityContainer _container;

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
        var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);

        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }

    protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
        var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);

        foreach (var attribute in attributes) {
            _container.BuildUp(attribute.GetType(), attribute);
        }

        return attributes;
    }
}

Dan kemudian mendefinisikan ini dalam file Global.asax saya seperti:

FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

Ini berfungsi dengan baik tetapi saya bertanya-tanya apakah ini cara yang benar untuk melakukannya? Untuk mengatasi kasus kedua saya cukup mengubah tempat saya mendefinisikan filter global saya menjadi yang berikut:

GlobalFilters.Filters.Add(DependencyResolver.Current.GetService<TestAttribute>());

Ini lagi-lagi berhasil, tetapi apakah ini cara yang benar untuk melakukannya?

Saya akan menghargai bantuannya. Terima kasih


person nfplee    schedule 30.05.2012    source sumber
comment
Tampaknya .Net 4 tidak menyediakan kait untuk ASP.NET MVC untuk memasukkan dependensi ke halaman tata letak. Solusi untuk atribut filter tampaknya berfungsi dengan baik tetapi Anda mungkin ingin memasukkan dependensi global dengan lebih baik dengan mengganti metode GetFilters dari kelas FilterAttributeFilterProvider dan memasukkan dependensi serupa dengan yang dilakukan di 2 metode lainnya.   -  person nfplee    schedule 19.06.2012
comment
Jangan gunakan Dependency Resolver karena rusak. Tetap dengan injeksi konstruktor.   -  person CrazyCoderz    schedule 06.08.2012
comment
Untuk menjawab pertanyaan Anda, apakah ini cara yang benar untuk melakukannya? Saya tidak akan melakukannya seperti itu.   -  person CrazyCoderz    schedule 06.08.2012
comment
Injeksi konstruktor bukanlah pilihan dengan tampilan.   -  person Casey    schedule 25.04.2014