AutoFac

Stella981
• 阅读 611

一、前言

  AutoFac是.NET平台下的一款著名的IoC Container,它可以让我们很轻松的解除项目中服务类的接口与客户类的接口实现类之间的依赖关系,从而降低系统各模块之间耦合程度以提高系统的稳定性。最近在做毕业设计,在开发中采用了autofac来进行依赖注入,这里是对踩到的一些坑的解决方法,希望可以给同样不幸进入这些坑中的童鞋们提供一些解决思路。

  对于IOC、DI相关的概念由于自己也是一知半解的,推荐T2噬菌体的这篇 依赖注入那些事儿 写的很详细也很好理解。

  AutoFac文档地址:http://autofac.readthedocs.io/en/latest/getting-started/index.html

  使用AutoFac需要引用的类库dll:_Autofac.dllAutofac.ConfigurationMicrosoft.Extensions.Configuration.Xml_

  PS:我是采用xml进行配置的AutoFac,如果你采用json进行配置,则需要引用_Microsoft.Extensions.Configuration.Xml_,使用nuget即可获取到这些引用dll。

二、实例

  项目结构如下图所示,autofac涉及到类库如下

  PSU.Factory:autofac配置相关信息

  PSU.Domain:功能接口的实现类

  PSU.IService:功能接口

  PSU.Controllers:控制器

AutoFac

  PSU.IService、PSU.Domain就是基本的接口与其实现类,也就没什么东西了,测试的代码如下:

AutoFac AutoFac

 1 //-----------------------------------------------------------------------
 2 // <copyright file= "IIndex.cs">
 3 //     Copyright (c) Danvic712. All rights reserved.
 4 // </copyright>
 5 // Author: Danvic712
 6 // Date Created: 2018/1/9 星期二 16:37:48
 7 // Modified by:
 8 // Description: 管理员首页操作邻域
 9 //-----------------------------------------------------------------------
10 using PSU.Models.Area.Administrator.Home;
11 using System;
12 using System.Collections.Generic;
13 using System.Linq;
14 using System.Text;
15 using System.Threading.Tasks;
16 
17 namespace PSU.IService.Area.Administrator.Home
18 {
19     public interface IIndex
20     {
21         /// <summary>
22         /// 页面初始化加载
23         /// </summary>
24         /// <param name="webModel"></param>
25         /// <returns></returns>
26         IndexWebModel Init(IndexWebModel webModel);
27     }
28 }

接口定义

AutoFac AutoFac

 1 //-----------------------------------------------------------------------
 2 // <copyright file= "IndexDomain.cs">
 3 //     Copyright (c) Danvic712. All rights reserved.
 4 // </copyright>
 5 // Author: Danvic712
 6 // Date Created: 2018/1/9 星期二 16:42:53
 7 // Modified by:
 8 // Description: 管理员首页操作邻域接口实现
 9 //-----------------------------------------------------------------------
10 using PSU.IService.Area.Administrator.Home;
11 using PSU.Models.Area.Administrator.Home;
12 using System;
13 
14 namespace PSU.Domain.Area.Administrator.Home
15 {
16     public class IndexDomain : IIndex
17     {
18         /// <summary>
19         /// 页面初始化加载
20         /// </summary>
21         /// <param name="webModel"></param>
22         /// <returns></returns>
23         public IndexWebModel Init(IndexWebModel webModel)
24         {
25             webModel = new IndexWebModel();
26             return webModel;
27         }
28     }
29 }

接口实现类

   PSU.Factory这个类库里写的是autofac的配置方法,在写之前让我们先看看官方的Demo:

AutoFac

AutoFac

   简单翻译一下

  1. 你需要在你的项目里加载Microsoft.Extensions.Configuration 这个dll,如果你使用json进行配置的话,你需要加载 Microsoft.Extensions.Configuration.Json 这个dll,而我是通过xml文件进行配置,则需要加载 Microsoft.Extensions.Configuration.Xml
  2. 通过实例化ConfigurationBuilder来加载配置文件
  3. 注册配置组件
  4. 在容器中注册配置模块

因为我们会把所有的接口与实现类的映射放置于xml文件中,将所有的模块注册在容器中,通过对于官方方法的封装,创建一个静态方法去自由的选择加载需要接口与实现类,代码和配置文件如下:

AutoFac AutoFac

 1 //-----------------------------------------------------------------------
 2 // <copyright file= "MAutoFac.cs">
 3 //     Copyright (c) Danvic712. All rights reserved.
 4 // </copyright>
 5 // Author: Danvic712
 6 // Date Created: 2018/1/8 星期一 13:23:04
 7 // Modified by:
 8 // Description: AutoFac帮助类
 9 //-----------------------------------------------------------------------
10 using Autofac;
11 using Autofac.Configuration;
12 using Microsoft.Extensions.Configuration;
13 
14 namespace PSU.Factory
15 {
16     public class MAutoFac
17     {
18         /// <summary>
19         /// 缓存注册容器
20         /// </summary>
21         private static IContainer _container = null;
22 
23         /// <summary>
24         /// 注册并创建实例
25         /// </summary>
26         /// <typeparam name="T"></typeparam>
27         /// <returns></returns>
28         public static T CreateInstance<T>()
29         {
30             if (_container == null)
31             {
32                 var builder = new ContainerBuilder();
33 
34                 //读取配置信息
35                 //
36                 IConfigurationBuilder config = new ConfigurationBuilder();
37                 config.AddXmlFile("autofac.config");
38 
39                 //注册组件
40                 var module = new ConfigurationModule(config.Build());
41 
42                 //注册模块
43                 builder.RegisterModule(module);
44 
45                 _container = builder.Build();
46             }
47 
48             return _container.Resolve<T>();
49         }
50     }
51 }

帮助类

AutoFac AutoFac

1 <?xml version="1.0" encoding="utf-8" ?>
2 <autofac defaultAssembly="PSU.IService">
3   <!--Administrator:首页接口-->
4   <components name="0">
5     <type>PSU.Domain.Area.Administrator.Home.IndexDomain,PSU.Domain</type>
6     <services name="0" type="PSU.IService.Area.Administrator.Home.IIndex" />
7     <injectProperties>true</injectProperties>
8   </components>
9 </autofac>

配置文件

  创建一个返回类型是泛型的静态方法,通过 Resolve() 用来解析容器中已经注册的实例T,并对给其进行赋值,这样,我们就可以通过传入指定的接口来获取对应的实现方法。

对于XML配置文件,如果你是采用VS生成的配置文件模版,你需要移除 configuration 根节点,直接使用 autofac 作为XML文档的根节点,切记,否则你将无法读取到配置信息。同时,如果你是和我一样的直接写好配置文件的地址,你需要将配置文件放置在Web项目的根目录下,或者显示写好加载的配置文件的所在地址。

配置相关解释:

1、defaultAssembly 默认的命名空间;如果type节点或者services节点的属性type没有设置类所在命名空间的话,将默认在defaultAssembly下查找类,type节点和services节点的属性type设置格式为MyType,MyAssembly;

2、多个接口时添加多个components节点,name 属性依次添加;

3、type节点对应接口实现类所在的位置(命名空间.类名,命名空间) --- 英文逗号;

4、services节点对应接口所在的位置(命名空间.接口类名)

5、injectProperties节点:是否启用组件的属性注入

在控制器调用接口实例,我是采用的重写 Controller 类的 Inintalize 方法,实现接口的注入,这样我们就可以在控制器中调用接口里的方法了,实现方法如下图所示。

AutoFac AutoFac

 1 //-----------------------------------------------------------------------
 2 // <copyright file= "HomeController.cs">
 3 //     Copyright (c) Danvic712. All rights reserved.
 4 // </copyright>
 5 // Author: Danvic712
 6 // Date Created: 2017/12/20 星期三 14:20:40
 7 // Modified by:
 8 // Description: Administrator-Home控制器
 9 //-----------------------------------------------------------------------
10 using PSU.Factory;
11 using PSU.IService.Area.Administrator.Home;
12 using PSU.Models.Area.Administrator.Home;
13 using System.Web.Mvc;
14 using System.Web.Routing;
15 
16 namespace PSU.Controllers.Areas.Administrator
17 {
18     public class HomeController : Controller
19     {
20         #region Initializes
21 
22         private IIndex _iService;
23 
24         protected override void Initialize(RequestContext requestContext)
25         {
26             base.Initialize(requestContext);
27 
28             if (_iService == null)
29             {
30                 _iService = MAutoFac.CreateInstance<IIndex>();
31             }
32         }
33 
34         #endregion
35 
36         #region Service
37 
38         public ActionResult Index(IndexWebModel webModel)
39         {
40             _iService.Init(webModel);
41             return View(webModel);
42         }
43 
44         #endregion
45     }
46 }

控制器

   至此,我们要完成的也就差不多了,运行项目看看,咦,发现报错,查看报错信息,提示我们找不到PSU.Domain这个类库dll

AutoFac

  Web项目,它所依赖的dll全部位于网站根目录下面的bin文件夹中,由于我们采用IOC加载接口实现层,Web层只引用接口,不引用接口实现层,所以autofac无法在项目中找到PSU.Domain这个dll,所以我们只要把这个dll给移动到Web项目的bin目录下面就可以了。编译生成后手动移动,繁琐、费事。这里我采用的是通过在PSU.Domain这里类库的属性上添加后期生成命令完成操作。重新生成下项目,预览这个视图页面,bingo,可以了。

AutoFac

三、其它

  1、通过属性后期生成事件生成接口实现类库到bin文件夹里,有人说在release模式下,执行失败,我还没到这一步,所以就不得而知了,解决方案可以见链接 =》https://social.msdn.microsoft.com/Forums/zh-CN/caf363ec-e0f9-41da-ad24-60993e83f190/releasebindll?forum=adonetzhchs

  2、代码完成之后,才发现AutoFac有专门的一个在MVC项目如何使用的实例,如果有童鞋用过的话,可以说说这两种的优劣,示例见链接 =》http://autofac.readthedocs.io/en/latest/integration/mvc.html

  3、个人的一点使用实例,希望对你有点用处,如果中间有说的不对的地方,欢迎指点

  4、欢迎转载,注明出处即可

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
2年前
AutoFac简介
在.NET上现在存在许多的依赖注入容器,如:CastleWindsor、StructureMap、Autofac、Unity。这里主要介绍一下Autofac,Autofac和其他容器的不同之处是它和C语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成。Autofac的主要特性如下:1)灵活的组件实例化:
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这