一、为什么使用AutoFac
Autofac是一款IOC框架,比较于其他的IOC框架,如 Spring.NET,Unity,Castle等等所包含的,它很轻量级性能上非常高。
官方网站:http://autofac.org/
源码下载地址:https://github.com/autofac/Autofac
引用博客地址:
https://blog.csdn.net/silasila__/article/details/79450512
https://www.cnblogs.com/liupeng/p/4806184.html
控制反转(IoC/Inverse Of Control):调用者不再创建被调用者的实例,由autofac框架实现(容器创建)所以称为控制反转。
依赖注入(DI/Dependence injection) :容器创建好实例后再注入调用者称为依赖注入。
二、AutoFac的使用
首先你必须获取AutoFac,这里你可以通过各种方式加载它,我这里还是通过VS中的NuGet来加载AutoFac,不论是哪种方式,最终的目的就是将 Autofac.dll,Autofac.Configuration.dll 这两个程序集引用到你的项目中。
三、AutoFac常用方法说明
(1)builder.RegisterType().As():注册类型及其实例。例如下面就是注册接口IDAL的实例SqlDAL
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<SqlDAL>().As<IDAL>();
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.Resolve<IDAL>();
(2)IContainer.Resolve():解析某个接口的实例。例如上面的最后一行代码就是解析IDAL的实例SqlDAL
(3)builder.RegisterType().Named(string name):为一个接口注册不同的实例。有时候难免会碰到多个类映射同一个接口,比如SqlDAL和OracleDAL都实现了IDAL接口,为了准确获取想要的类型,就必须在注册时起名字。
builder.RegisterType<SqlDAL>().Named<IDAL>("sql");
builder.RegisterType<OracleDAL>().Named<IDAL>("oracle");
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.ResolveNamed<IDAL>("sql");
OracleDAL oracleDAL = (OracleDAL)container.ResolveNamed<IDAL>("oracle");
(4)IContainer.ResolveNamed(string name):解析某个接口的“命名实例”。例如上面的最后一行代码就是解析IDAL的命名实例OracleDAL
(5)builder.RegisterType().Keyed(Enum enum):以枚举的方式为一个接口注册不同的实例。有时候我们会将某一个接口的不同实现用枚举来区分,而不是字符串,例如:
public enum DBType{ Sql, Oracle}
builder.RegisterType<SqlDAL>().Keyed<IDAL>(DBType.Sql);
builder.RegisterType<OracleDAL>().Keyed<IDAL>(DBType.Oracle);
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.ResolveKeyed<IDAL>(DBType.Sql);
OracleDAL oracleDAL = (OracleDAL)container.ResolveKeyed<IDAL>(DBType.Oracle);
(6)IContainer.ResolveKeyed(Enum enum):根据枚举值解析某个接口的特定实例。例如上面的最后一行代码就是解析IDAL的特定实例OracleDAL
(7)builder.RegisterType().InstancePerDependency():用于控制对象的生命周期,每次加载实例时都是新建一个实例,默认就是这种方式
(8)builder.RegisterType().SingleInstance():用于控制对象的生命周期,每次加载实例时都是返回同一个实例
(9)IContainer.Resolve(NamedParameter namedParameter):在解析实例T时给其赋值
DBManager manager = container.Resolve<DBManager>(new NamedParameter("name", "SQL"));
public class DBManager
{
IDAL dal;
public DBManager (string name,IDAL _dal)
{
Name = name;
dal= _dal;
}
}
四、通过配置的方式使用AutoFac
(1)先配置好配置文件
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
</configSections>
<autofac defaultAssembly="ConsoleApplication1">
<components>
<component type="ConsoleApplication1.SqlDAL, ConsoleApplication1" service="ConsoleApplication1.IDAL" />
</components>
</autofac>
</configuration>
(2)读取配置实现依赖注入(注意引入Autofac.Configuration.dll)
static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<DBManager>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
using (IContainer container = builder.Build())
{
DBManager manager = container.Resolve<DBManager>();
manager.Add("INSERT INTO Persons VALUES ('Man', '25', 'WangW', 'Shanghai')");
}
}
五、ASP.NET MVC与AtuoFac
终于到了ASP.NET MVC与AtuoFac双剑合璧的时候了,下面就看看AtuoFac在MVC中的应用,其实很简单,大概就几个步骤搞定:
1、首先在函数Application_Start() 注册自己的控制器类,一定要引入Autofac.Integration.Mvc.dll
namespace AtuoFacOfMVC4
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var builder = new ContainerBuilder();
SetupResolveRules(builder);
builder.RegisterControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
private void SetupResolveRules(ContainerBuilder builder)
{
builder.RegisterType<StudentRepository>().As<IStudentRepository>();
}
}
}
2、现在在你的MVC程序中注入依赖代码
(1)首先声明一个Student学生类
namespace AtuoFacOfMVC4.Models
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Graduation { get; set; }
Public string School { get; set; }
public string Major { get; set; }
}
}
(2)然后声明仓储接口及其实现
namespace AtuoFacOfMVC4.Models
{
public interface IStudentRepository
{
IEnumerable<Student> GetAll();
Student Get(int id);
Student Add(Student item);
bool Update(Student item);
bool Delete(int id);
}
}
(3)最后添加控制器StudentController,并注入依赖代码
namespace AtuoFacOfMVC4.Controllers
{
public class StudentController : Controller
{
readonly IStudentRepository repository;
//构造器注入
public StudentController(IStudentRepository repository)
{
this.repository = repository;
}
public ActionResult Index()
{
var data = repository.GetAll();
return View(data);
}
}
}
(四)属性注入
public class DefaultController : Controller
{
public IDataSource ds { get; set; }
// 接口定义 构造函数注入
//public DefaultController(IDataSource _ds)
//{
// ds = _ds;
//}
// GET: Default
public ActionResult Index()
{
//调用具体类的具体方法返回结果 赋值给ViewBag.Message
ViewBag.Message = "STONE刘先生:" + ds.GetData();
return View();
}
}
如果现在任何地方都不改的情况下,是不是提醒ds为null,那怎么支持属性注入呢!
builder.RegisterControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
把Global.asax里面的这句改成如上这句 就好了!
六、自动注入
Autofac提供一个RegisterAssemblyTypes方法。它会去扫描所有的dll并把每个类注册为它所实现的接口。既然能够自动注入,那么接口和类的定义一定要有一定的规律。我们可以定义IDependency接口的类型,其他任何的接口都需要继承这个接口。比如
public interface IDependency
{
}
业务逻辑实现——岗位管理
public class PostService : IDependency
{
public IPostService postService { get; set; }
........
}
自动注入原理说明:
首先我们去找到所有Dll,再去找到实现了IDependency接口的类,然后使用RegisterAssemblyTypes进行注入。
Assembly[] assemblies = Directory.GetFiles(AppDomain.CurrentDomain.RelativeSearchPath, "*.dll").Select(Assembly.LoadFrom).ToArray();
//注册所有实现了 IDependency 接口的类型
Type baseType = typeof(IDependency);
builder.RegisterAssemblyTypes(assemblies)
.Where(type => baseType.IsAssignableFrom(type) && !type.IsAbstract)
.AsSelf().AsImplementedInterfaces()
.PropertiesAutowired().InstancePerLifetimeScope();
//注册MVC类型
builder.RegisterControllers(assemblies).PropertiesAutowired();
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));