[转载]ASP.NET MVC3中用内置的MEF实现IoC

[转载]ASP.NET MVC3中用内置的MEF实现IoC – Mainz – 博客园.

本文讲述关于用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的模块化开发有兴趣可以参考 这篇文章

本文源码下载这里
赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏