ASP.NET MVC3中用內建的MEF實現IoC

來源:互聯網
上載者:User

本文講述關於用Managed Extensibility Framework (MEF) 的方法來實現IoC和Asp.net的整合。很多人不知道,這個MEF貌似是個大架構,其實已經內建在.NET Framework 4.0裡面了,只需要添加引用System.ComponentModel.Composition即可。MEF在Microsoft的人看來不是一個IoC/DI的工具,而是一個提供輕量級的、可擴充的、類似外掛程式式的系統架構的、且無需配置的(Attribute Based)架構。雖然微軟的人極力否認MEF是一個IoC/DI的工具,但事實是它的確可以實現Ioc/DI。而且相對於Spring.net這樣的架構來說,它的優勢就是首先它是.NET Framework內建的,你無需添加第三方的引用,擔心第三方組件的更新等問題;其次它是免配置的,對Spring.net這樣的龐然大物來說免配置很有誘惑力。對Unity來說,它的優勢是一樣的,.NET Framework內建,無需配置,無需hard code的聲明。當然更無需直接引用了,這是所有IoC都做到的。MEF還可以通過metadata自動探索Parts而無需擷取parts的assembly/dll。有關MEF的完整的介紹,請移步MSDN:http://msdn.microsoft.com/en-us/library/dd460648.aspx。

這裡給出一個例子,用在Asp.net MVC3裡面,主要情境是在Controller裡通過介面擷取中介層的執行個體,本文主要是示範MEF在Asp.net MVC3中的應用,其它豐富的應用完全可以發揮你自己的想象力。本文源碼下載在這裡。

整個項目的結構如:

 

在Controller中需要調用IBookService與IPhoneService:

  

Controller的代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Service.Interface;

namespace Mvc3_MEF_WebApplication.Controllers
{
    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class HomeController : Controller
    {
        private readonly IBookService _bookService;
        private readonly IPhoneService _phoneService;

        [ImportingConstructor]
        public HomeController(IBookService bookService, IPhoneService phoneService)
        {
            _bookService = bookService;
            _phoneService = phoneService;
        }

        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!" + 
                _bookService.GetAllBooks().ToList()[0].Name + 
                _phoneService.GetAllPhones().ToList()[0].SerialNumber;

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}

BookService的實現:

 

BookService的代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using Data.Model;
using Service.Interface;

namespace Service.Implement
{
    [Export(typeof(IBookService))]
    public class DefaultBookService : IBookService
    {
        public IEnumerable<Book> GetAllBooks()
        {
            yield return new Book
            {
                ID = 1,
                Name = "a"
            };

            yield return new Book
            {
                ID = 2,
                Name = "b"
            };
        }
    }
}

在Global.asax.cs裡面需要設定MEF dependency resolver,自動載入所有bin目錄下面的assembly/dll

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            //Set MEF dependency resolver
            var catalog =
               new DirectoryCatalog(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"));
            var container =
                new CompositionContainer(catalog);
            container.ComposeParts(this);

            var mefDependencySolver = new MefDependencySolver(container);
            DependencyResolver.SetResolver(mefDependencySolver);
        }

 

MefDependencySolver的代碼:

 

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Web.Mvc;

namespace Mvc3_MEF_WebApplication.Extension
{
    public class MefDependencySolver : IDependencyResolver
    {
        public MefDependencySolver(CompositionContainer compositionContainer)
        {
            _compositionContainer = compositionContainer;
        }

        private readonly CompositionContainer _compositionContainer;

        public object GetService(Type serviceType)
        {
            var name = AttributedModelServices.GetContractName(serviceType);
            return _compositionContainer.GetExportedValueOrDefault<object>(name);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _compositionContainer
                       .GetExportedValues<object>(serviceType.FullName);
        }
    }
}

 

 

 

最後系統啟動並執行結果如:

 

 

小結

總結一下所有的步驟:

1. 項目添加引用: System.ComponentModel.Composition

2. 為需要的Parts標註[Import] [Export] 等attribute

3. 建立一個CompositionContainer執行個體

4. 實現IDependencyResolver介面

5. 註冊到DependencyResolver

 

更多資源

本文的實現很簡單,拋磚引玉,更多內容可以參考以下資料:

1. MSDN: MEF Overview

2. MEF Programming Guide

3. MSDN Magazine: Building Composable Apps in .NET 4 with the Managed Extensibility Framework

 

另外StackOverflow還有很多針對MEF進階議題(importMany集合匯入, lazy惰性匯入, composition/AllowMultiple複合,  metaData, lifetime等進階議題。)的討論,可以參考下。

 

此外,用MEF為Asp.net mvc 建立一個ControllerFactory可以參考這篇文章。 (用Unity的可以參考Artech的這篇文章。)

用MEF實現Asp.net MVC的模組化開發有興趣可以參考 這篇文章。

 

 

本文源碼下載在這裡。

 

 

相關關鍵詞:
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.