zoukankan      html  css  js  c++  java
  • 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文件夹中。

    [csharp] view plain copy
     
    1. public class TxtLog:ILog  
    2. {  
    3.      public void Save(string message)  
    4.      {  
    5.          //save as txt  
    6.      }  
    7. }  


    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();
        }

        //....

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

    [csharp] view plain copy
     
    1. <h2>ILog's type name is @ViewBag.LogTypeName</h2>  


     

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

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

    [csharp] view plain copy
     
    1. protected void Application_Start()  
    2. {  
    3.      ......  
    4.   
    5.      ContainerBuilder builder = new ContainerBuilder();  
    6.      builder.RegisterControllers(Assembly.GetExecutingAssembly());  
    7.      builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())  
    8.          .AsImplementedInterfaces();  
    9.        
    10.      var container = builder.Build();  
    11.      DependencyResolver.SetResolver(new AutofacDependencyResolver(container));  
    12. }  


     

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

    image

    autofac应对需求变更

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

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

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

    [csharp] view plain copy
     
    1. public class DbLog:ILog  
    2. {  
    3.      public void Save(string message)  
    4.      {  
    5.          //save to Db.  
    6.      }  
    7. }  


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

    [csharp] view plain copy
     
    1. builder.RegisterType<DbLog>().As<ILog>();  


     

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

    image

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

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

    [csharp] view plain copy
     
    1. public class HomeController : Controller  
    2. {  
    3.      private ILog _log;  
    4.      private IEnumerable<ILog> _logList;  
    5.      public HomeController(ILog log,IEnumerable<ILog> logList )  
    6.      {  
    7.          _log = log;  
    8.          _logList = logList;  
    9.      }  
    10.   
    11.      public ActionResult Index()  
    12.      {  
    13.          ViewBag.Message = "Welcome to ASP.NET MVC!";  
    14.          ViewBag.LogTypeName = _log.GetType().Name;  
    15.          ViewBag.LogTypeNames = _logList.Select(x => x.GetType().Name).Aggregate((x, y) => x+","+y );  
    16.            
    17.          return View();  
    18.      }  


     

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

    image

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

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

    [csharp] view plain copy
     
    1. public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle>  
    2.      RegisterControllers(  
    3.          this ContainerBuilder builder,  
    4.          params Assembly[] controllerAssemblies)  
    5. {  
    6.      return builder.RegisterAssemblyTypes(controllerAssemblies)  
    7.          .Where(t => typeof(IController).IsAssignableFrom(t) &&  
    8.              t.Name.EndsWith("Controller"));  
    9. }  


     

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

    结语

    未完,待续……^_^

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

  • 相关阅读:
    MySql安装方法和配置、解决中文乱码
    医疗器械软件安全性级别判定
    工业镜头视场、倍率、焦距之间的关系
    C#一个进程监控另一进程的用户界面是否响应系统
    TextEdit验证
    "tsc.exe"已退出,代码1
    截取上传视频的第一帧作为封面的方法
    汉堡也会结对子
    第二次作业——全国中小学生数学(四则运算)竞赛
    第二次作业——全国中小学生数学(四则运算)竞赛(更改版)
  • 原文地址:https://www.cnblogs.com/Alex80/p/5595504.html
Copyright © 2011-2022 走看看