【.Net码农】【Autofac】Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac

http://www.cnblogs.com/hkncd/archive/2012/11/28/2792474.html


Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac


经过上篇蜻蜓点水的介绍后,本篇通过实例快速上手autofac,展示当asp.net mvc引入了autofac之后会带来什么。

创建Asp.net MVC并引入Autofac

首先,创建一个MVC站点,为方便起见,选初始带HomeControllerAccountController的那种。然后通过NuGet或到Autofac官网下载来引入类库。个人推荐前者,因为从VS2010开始,已内集可视化的NuGet功能,使用起来非常方便。如下图所示:

image

这是vs2012的界面,点击“Manage NuGet Packages…”,弹出窗体如下,在右上角搜索框中输入“Autofac”,找到对应的库点击安装即可。这里需要应用的库有两个“Autofac”和“Autofac ASP.Net MVC3 Integration”。

image

autofac实现对Controller的自动注入

现在HomeController需要用到日志记录功能。沿用上篇ILog接口,假设目前已有一种ILog的实现类--TxtLog,放在根目录下Services文件夹中。

public   class   TxtLog : ILog
{
     public   void  Save( string  message)
     {
         //save as txt
     }
}

HomeController需添加一个ILog类型变量,为了直观看到类名,我把_log的类名赋给ViewBag.LogTypeName并显示出来。代码如下:

public   class   HomeController  :  Controller
{
     private   ILog  _log;
    
     public  HomeController( ILog  log)
     {
         _log = log;
     }

     public   ActionResult  Index()
     {
         ViewBag.Message =  "Welcome to ASP.NET MVC!" ;
         ViewBag.LogTypeName = _log.GetType().Name;
       
         return  View();
     }

     //....

接着,在对应页面加入以下代码(抱歉这里用英文描述,因为我的代码高亮插件不能显示中文):

< h2 > ILog's type name is  @ ViewBag.LogTypeName </ h2 >

此时运行程序会报错,因为HomeController找不到无参构造函数,而我们也没有给_log指定任何类型的实例。

现在我们让Autofac发挥作用,在Global文件的Application_Start方法中添加配置代码,如下:

protected   void  Application_Start()
{
     ......

     ContainerBuilder builder =  new   ContainerBuilder ();
     builder.RegisterControllers( Assembly .GetExecutingAssembly());
     builder.RegisterAssemblyTypes( Assembly .GetExecutingAssembly())
         .AsImplementedInterfaces();
    
     var  container = builder.Build();
     DependencyResolver .SetResolver( new   AutofacDependencyResolver (container));
}

先不管含义,加了这些代码以后,再运行程序,会发现HomeControllerILog变量被赋予了TxtLog类型的实例,而我们并没有做任何new操作,结果如下图:

image

 

autofac应对需求变更

回头再看Application_Start中配置文件的代码:

  1. builder.RegisterControllers注册了当前程序集内所有的Controller类。
  2. builder.RegisterAssemblyTypes注册了当前程序集内的所有类。

如果此刻需求改变,我们需要将所有的TxtLog换成DbLog,该怎么办?首先添加DBLog类,如下:

public   class   DbLog : ILog
{
     public   void  Save( string  message)
     {
         //save to Db.
     }
}

然后在Application_Start的方法的末端处添加如下代码:

builder.RegisterType< DbLog >().As< ILog >();

运行程序,看到页面如下:

image

可看出ILog的类型已变成了DbLog。但为何要强调末端处?实际上,DBLog已经通过builder.RegisterAssemblyTypes被注册过一次,如果对同一个类型或接口注册多次(比如这里的ILog),在Autofac中会以列表的形式保存,如果只取一个,则Autofac会从列表返回最新的那个

为了证明,我们在HomeController中再加入一个变量,类型为IEnumerable<ILog>,然后将列表中所有类名显示出来,用逗号隔开。

public   class   HomeController  :  Controller
{
     private   ILog  _log;
     private   IEnumerable < ILog > _logList;
     public  HomeController( ILog  log, IEnumerable < ILog > logList )
     {
         _log = log;
         _logList = logList;
     }

     public   ActionResult  Index()
     {
         ViewBag.Message =  "Welcome to ASP.NET MVC!" ;
         ViewBag.LogTypeName = _log.GetType().Name;
         ViewBag.LogTypeNames = _logList.Select(x => x.GetType().Name).Aggregate((x, y) => x+ "," +y );
        
         return  View();
     }

运行程序,页面显示如下:

image

可以看到,针对ILog接口注册了三个类型。前两个通过builder.RegisterAssemblyTypes注册,最后一个是我们手动添加。

但重复的注册类型总让人觉得不够优雅,因此实际开发中并不推荐一次性注册所有类,可条件筛选。翻开Autofac的源码,查看我们上文用到的builder.RegisterControllers会发现方法内部就是这种思路:

public   static   IRegistrationBuilder < object ScanningActivatorData DynamicRegistrationStyle >
     RegisterControllers(
         this   ContainerBuilder  builder,
         params   Assembly [] controllerAssemblies)
{
     return  builder.RegisterAssemblyTypes(controllerAssemblies)
         .Where(t =>  typeof ( IController ).IsAssignableFrom(t) &&
             t.Name.EndsWith( "Controller" ));
}

由代码可知,该方法筛选出所有实现IController接口且类型名以“Controller”结尾的类。你可以根据自己项目的实际情况来筛选,很多使用Autofac的开源站点也都是这么做的。

结语

未完,待续……^_^

声明:个人博客已迁移到Github此处,新博客内容大多与前端技术相关。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值