ASP.NET MVC3中用内置的MEF实现IoC
本文讲述关于用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.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.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
{
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);
}
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
更多资源
本文的实现很简单,抛砖引玉,更多内容可以参考以下资料:
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的模块化开发有兴趣可以参考 这篇文章。
@:博主推荐您使用Firefox,Chrome或Opera浏览器浏览以获得最佳视觉效果
@:Mainz → http://www.cnblogs.com/Mainz → 博文如非注明,均为原创,敬请注意.
®: 博文是本人当时的学习笔记及知识整理,由于自身局限错误在所难免,敬请斧正. 博文中源码只作为例子学习参考之用,不保证能运行,对后果不负任何责且无任何质保,如有不明请给我留言
©: 本文版权属于博客园和本人,版权基于署名 2.5 中国大陆许可协议发布,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接和署名Mainz(包含链接),不得删节,否则保留追究法律责任的权利。
ASP.NET MVC3中用内置的MEF实现IoC
posted @ 2012-02-10 17:50 Mainz 阅读(938) | 评论 (13) 编辑
私有静态方法private static method-值得用吗?
posted @ 2011-12-14 12:06 Mainz 阅读(159) | 评论 (0) 编辑
今天代码Review发现的C#闭包问题,请做题
posted @ 2011-11-02 12:04 Mainz 阅读(2007) | 评论 (33) 编辑
MEF的ImportingConstructor的异常处理
posted @ 2011-10-17 10:48 Mainz 阅读(255) | 评论 (0) 编辑
用并发队列(ConcurrentQueue)实现多线程任务中随时异步回调进度通知(.Net4.0)
posted @ 2011-10-13 10:56 Mainz 阅读(383) | 评论 (4) 编辑
VisualStudioVS2010统计代码行数(免安装插件)
posted @ 2011-09-28 12:17 Mainz 阅读(614) | 评论 (0) 编辑
[.NET]Event handler没有注销就会内存泄露吗?
posted @ 2011-09-10 14:20 Mainz 阅读(249) | 评论 (0) 编辑
C#的Dictionary值排序和SortedDictionary键排序
posted @ 2011-06-29 10:25 Mainz 阅读(1569) | 评论 (1) 编辑
WeakPropertyChangedListener用弱引用事件订阅防止内存泄露
posted @ 2011-06-25 15:25 Mainz 阅读(246) | 评论 (0) 编辑
Failed to access IIS metabase(IIS Exception Problem)
posted @ 2011-05-18 09:40 Mainz 阅读(412) | 评论 (0) 编辑
[Silverlight入门系列]Silverlight卡片翻转动画效果/x轴Y轴Z轴旋转
posted @ 2011-04-27 11:54 Mainz 阅读(613) | 评论 (1) 编辑
动态设置和修改Membership/Profile/RoleProvider的ConnectionString数据库连接字符串
posted @ 2011-04-14 16:12 Mainz 阅读(289) | 评论 (0) 编辑
LINQ使用细节之.AsEnumerable()和.ToList()的区别
posted @ 2011-04-08 15:04 Mainz 阅读(1090) | 评论 (3) 编辑
初识LINQ中的Expression表达式树
posted @ 2011-03-11 16:40 Mainz 阅读(430) | 评论 (0) 编辑
C#的delegate/event/Action/Func/Predicate关键字
posted @ 2011-03-11 12:53 Mainz 阅读(906) | 评论 (4) 编辑
C#4.0的dynamic和var及object关键字辨析
posted @ 2011-03-10 18:01 Mainz 阅读(518) | 评论 (2) 编辑
protobuf/json/xml/binary/Thrift数据交换
posted @ 2011-03-07 10:58 Mainz 阅读(1243) | 评论 (0) 编辑
生产中遇到的IIS启用GZip的深层问题
posted @ 2011-03-07 10:18 Mainz 阅读(217) | 评论 (0) 编辑
LINQ.Contains超过2100记录报异常Exception的问题
posted @ 2011-03-04 17:49 Mainz 阅读(468) | 评论 (0) 编辑
读取xml包含问号的错误:Data at the root level is invalid
posted @ 2011-01-18 16:19 Mainz 阅读(480) | 评论 (0) 编辑
搜索提示的实现(仿百度):附源码和在线demo
posted @ 2010-12-24 23:13 Mainz 阅读(905) | 评论 (10) 编辑
Aptana深色主题(编辑js,css,html)
posted @ 2010-12-06 16:57 Mainz 阅读(422) | 评论 (0) 编辑
使用Spring.NET统一ASP.NET异常处理并记录日志
posted @ 2010-12-06 11:53 Mainz 阅读(501) | 评论 (0) 编辑
新浪微博OAuth第三方登录C#源代码下载
posted @ 2010-12-01 17:54 Mainz 阅读(5516) | 评论 (83) 编辑
静态方法(Static)到底该不该用?
posted @ 2010-12-01 11:00 Mainz 阅读(556) | 评论 (2) 编辑
Remoting在多IP多网卡内外网环境下的问题
posted @ 2010-05-06 12:58 Mainz 阅读(468) | 评论 (2) 编辑
谈谈windows+IIS+.NET与Linux+Apache(Nginx)+Java之争
posted @ 2010-04-26 16:49 Mainz 阅读(645) | 评论 (1) 编辑
自动给URL地址加上超链接
posted @ 2009-12-14 10:56 Mainz 阅读(290) | 评论 (0) 编辑
使用Office组件读取Excel,引用Microsoft.Office.Interop.Excel出现的问题
posted @ 2009-11-11 16:49 Mainz 阅读(3577) | 评论 (3) 编辑
ASP.NET服务器控件刷新后仍旧保持滚动位置
posted @ 2009-08-21 17:47 Mainz 阅读(220) | 评论 (0) 编辑
显示ASP.NET页面装载进度
posted @ 2009-03-24 15:17 Mainz 阅读(514) | 评论 (4) 编辑
实用正则表达式匹配和替换
posted @ 2009-03-14 12:54 Mainz 阅读(1971) | 评论 (0) 编辑
读取SQLServer数据库存储过程列表及参数信息
posted @ 2008-11-23 16:52 Mainz 阅读(2724) | 评论 (8) 编辑
Windows系统单个进程最多线程数2000个?
posted @ 2008-09-23 20:35 Mainz 阅读(1602) | 评论 (0) 编辑
无缩进的XML字符串的处理
posted @ 2008-05-02 13:20 Mainz 阅读(197) | 评论 (0) 编辑
Tail -f
阅读全文
posted @ 2008-04-30 12:59 Mainz 阅读(105) | 评论 (0) 编辑
Array.Sort和快速排序
posted @ 2008-04-22 13:06 Mainz 阅读(1777) | 评论 (9) 编辑
反序列化的性能(Deserialization Performance)
posted @ 2008-04-16 11:24 Mainz 阅读(731) | 评论 (0) 编辑
[转]关于多线程并发:每个开发人员都应了解的内容
posted @ 2008-04-13 21:11 Mainz 阅读(942) | 评论 (0) 编辑
记录log中的16进制和ASCII码字符输出
posted @ 2008-04-11 12:32 Mainz 阅读(441) | 评论 (0) 编辑
string和byte[]的转换 (C#)
posted @ 2008-04-09 10:40 Mainz 阅读(27365) | 评论 (7) 编辑
C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全
posted @ 2008-04-06 13:50 Mainz 阅读(4047) | 评论 (3) 编辑
AppDomain以及如何改变web.config / App.config位置
posted @ 2008-04-03 10:47 Mainz 阅读(1347) | 评论 (1) 编辑