zoukankan      html  css  js  c++  java
  • Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac(转)

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

    创建Asp.net MVC并引入Autofac

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

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

    autofac实现对Controller的自动注入

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

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    public class TxtLog:ILog   
    {   
        public void Save(string message)   
        {   
            //save as txt   
        }   
    }

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

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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方法中添加配置代码,如下:

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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));   
    }

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

    autofac应对需求变更

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

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

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

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

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    public class DbLog:ILog   
    {   
        public void Save(string message)   
        {   
            //save to Db.   
        }   
    }

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

    双击代码全选
    1
    builder.RegisterType<DbLog>().As<ILog>();

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

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

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

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    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();   
        }

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

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

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

    双击代码全选
    1
    2
    3
    4
    5
    6
    7
    8
    9
    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的开源站点也都是这么做的。

    结语

    未完,待续……^_^

  • 相关阅读:
    FJNU 1151 Fat Brother And Geometry(胖哥与几何)
    FJNU 1157 Fat Brother’s ruozhi magic(胖哥的弱智术)
    FJNU 1159 Fat Brother’s new way(胖哥的新姿势)
    HDU 3549 Flow Problem(最大流)
    HDU 1005 Number Sequence(数列)
    Tickets(基础DP)
    免费馅饼(基础DP)
    Super Jumping! Jumping! Jumping!(基础DP)
    Ignatius and the Princess IV(基础DP)
    Keywords Search(AC自动机)
  • 原文地址:https://www.cnblogs.com/llkey/p/3725065.html
Copyright © 2011-2022 走看看