概念

Autofac是一个轻量级的依赖注入的框架,同类型的框架还有Spring.NET,Unity,Castle等;

ContainerBuilder:将组件注册成服务的创建者。

组件:Lambda表达式/一个类型/一个预编译的实例/实例类型所在的程序集

container 容器:通过 ContainerBuilder.Build()创建

获得对象:container.Resolve();

As()方法:可以指定相同的组件暴露成不同的服务。有些没有as就是将本身暴露给用户

 

组件注册成服务(暴露给用户)

常用注册的方式

1.通过RegisterType

2.同lambda表达式

3.通过实例来注册

4.程序集创建 RegisterAssemblyTypes

5.泛型注册 RegisterGeneric

  public class 注册方式
{
/// <summary>
/// 1.RegisterType AutoFac能够通过反射检查一个类型,选择一个合适的构造函数,创造这个对象的实例
/// </summary>
[TestMethod]
public void RegisterType()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>();//方式1
builder.RegisterType(typeof(TestClass));//方式2
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 1.RegisterType Named 命名方式注册
/// </summary>
[TestMethod]
public void RegisterType2()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
IContainer container = builder.Build();
// var class1 = container.Resolve<TestClass>(); error
var class2 = container.ResolveNamed<TestClass>("TestClass");
// Assert.IsTrue(class1 == null);
Assert.IsTrue(class2 != null);
} /// <summary>
/// 2.Lambda 通过反射的方式实现
/// </summary>
[TestMethod]
public void Lambda()
{
var builder = new ContainerBuilder();
builder.Register(p=>new TestClass());
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 3.RegisterInstance 实例创建
/// </summary>
[TestMethod]
public void RegisterInstance1()
{
var builder = new ContainerBuilder();
builder.RegisterInstance<TestClass>(new TestClass());
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 3.RegisterInstance 将自己系统中原有的单例注册为容器托管的单例
/// </summary>
[TestMethod]
public void RegisterInstance2()
{
var builder = new ContainerBuilder();
builder.RegisterInstance(TestClass2.GetInstance()).ExternallyOwned();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass2>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 4.RegisterAssemblyTypes 程序集的创建
/// </summary>
[TestMethod]
public void RegisterAssemblyTypes()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(Assembly.Load("UnitTestProject1")).Where(p => p.Name == "TestClass");
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// 5.RegisterGeneric 泛型注册
/// </summary>
[TestMethod]
public void RegisterGeneric()
{
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(TestClass3<>));
IContainer container = builder.Build();
var myIntList = container.Resolve<TestClass3<int>>();
Assert.IsTrue(myIntList != null);
var myStringList = container.Resolve<TestClass3<string>>();
Assert.IsTrue(myStringList != null);
} }

注册方式扩展

1.指定构造函数

2.构造函数的参数

3.属性注入

4.方法注入

    public class 注册方式扩展
{
/// <summary>
/// 构造函数注入
/// Autofac默认从容器中选择参数最多的构造函数。如果想要选择一个不同的构造函数,就需要在注册的时候就指定它。
/// *可以跟Name或者索引结合起来注册不同的构造函数
/// </summary>
[TestMethod]
public void RegisterType()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass4Paramter1>();
builder.RegisterType<TestClass4Paramter2>();
builder.RegisterType<TestClass4>().UsingConstructor(typeof(TestClass4Paramter1));
// builder.RegisterType<TestClass4>();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass4>();
Assert.IsTrue(class1.dd == );
} /// <summary>
/// 构造函数参数 WithParameters WithParameter
/// </summary>
[TestMethod]
public void RegisterType2()
{
var builder = new ContainerBuilder();
//错误情况 多个参数
//List<NamedParameter> ListNamedParameter = new List<NamedParameter>()
//{ new NamedParameter("paramter1", "dddd")
//};
//builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter); //错误
// builder.RegisterType<TestClass5>().WithParameter(new NamedParameter("paramter1", "dddd")); //错误
// List<ResolvedParameter> ListNamedParameter = new List<ResolvedParameter>()
// { new ResolvedParameter(
//(pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "paramter1",
//(pi, ctx) => "sectionName") // };
// builder.RegisterType<TestClass5>().WithParameters(ListNamedParameter); //正确情况
//builder.RegisterType<TestClass5>().WithParameter("paramter1", "sectionName"); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass5>();
Assert.IsTrue(class1.dd == );
} /// <summary>
///属性注入
/// </summary>
[TestMethod]
public void RegisterType3()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass6>().WithProperty("dd", );
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass6>();
Assert.IsTrue(class1.dd == );
} /// <summary>
///方法注入 指定注入的方法
/// </summary>
[TestMethod]
public void RegisterType4()
{
var builder = new ContainerBuilder();
builder.Register(c =>
{
var result = new TestClass7();
result.SetDependency(c.Resolve<ITestClass7>());
return result;
});
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass7>();
Assert.IsTrue(class1 != null);
} /// <summary>
///方法注入 使用Activating Handler 指定自身注册完成后触发的事件
/// </summary>
[TestMethod]
public void RegisterType5()
{
var builder = new ContainerBuilder();
builder.Register<TestClass8>(c => new TestClass8()).OnActivating(e => e.Instance.SetDependency(new TestClass6()));
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass8>();
Assert.IsTrue(class1 != null);
} } public class TestClass4
{
public int dd = ; public TestClass4(TestClass4Paramter1 a)
{
dd = ;
} public TestClass4(TestClass4Paramter2 a)
{
dd = ;
} public TestClass4(TestClass4Paramter1 a, TestClass4Paramter2 b)
{
dd = ;
} } public class TestClass4Paramter1
{ } public class TestClass4Paramter2
{ } public class TestClass5
{
public int dd = ;
public TestClass5(string a)
{
dd = ;
} } public class TestClass6
{ public int dd { get; set; }
} public class TestClass7
{
private ITestClass7 ITestClass7;
public void SetDependency(ITestClass7 ITestClass7)
{
this.ITestClass7 = ITestClass7;
}
} public interface ITestClass7
{ } public class TestClass8
{ public void SetDependency(TestClass6 ITestClass6)
{
var t = ITestClass6.dd;
}
}

获取服务

常用的获取服务的方式

  public class 获取服务
{
/// <summary>
/// Resolve
/// </summary>
[TestMethod]
public void Resolve()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
Assert.IsTrue(class1 != null);
} /// <summary>
/// ResolveNamed
/// </summary>
[TestMethod]
public void ResolveNamed()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Named<TestClass>("TestClass");
IContainer container = builder.Build();
var class2 = container.ResolveNamed<TestClass>("TestClass");
Assert.IsTrue(class2 != null);
} /// <summary>
/// ResolveKeyed 有Name的方式很方便,但是只支持字符串,但有时候我们可能需要通过其他类型作键。
/// </summary>
[TestMethod]
public void ResolveKeyed()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
IContainer container = builder.Build();
var class2 = container.ResolveKeyed<TestClass>(TestState.服务1);
Assert.IsTrue(class2 != null);
} [TestMethod]
public void ResolveIIndex()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().Keyed<TestClass>(TestState.服务1);
IContainer container = builder.Build();
IIndex<TestState, TestClass> IIndex = container.Resolve<IIndex<TestState, TestClass>>();
TestClass p = IIndex[TestState.服务1];
Assert.IsTrue(p != null);
}
}

获取服务扩展

当注册或者检索component的时候可以使用参数。

  1、传递参数给Resolve

  Resolve接受可变参数或IEnumerable<T>传入多个值

    using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
Console.WriteLine(manager.Name); //输出 刘备
manager.Say();
}

  此时,AutoFacManager下必须添加如下构造函数

    public AutoFacManager(string name,IPerson MyPerson)
{
Name = name;
person = MyPerson;
}

  2、可用的参数类型

  Autofac提供几种不同的参数对应策略:

  1. NamedParameter :像上面那样对应的参数名字
  2. TypedParameter:对应到参数的类型(必须是具体的类型)
  3. ResolvedParameter:灵活的参数匹配
  4. NamedParameter 和TypedParameter:只能提供常量参数

  3、从表达式中使用参数

  如果使用表达式注册的方式,可以使用第二个可用的委托参数来获得参数。

    builder.Register((c, p) => new AutoFacManager(p.Named<string>("name"), c.Resolve<IPerson>()));
builder.RegisterType<Worker>().As<IPerson>();
using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>(new NamedParameter("name", "刘备"));
Console.WriteLine(manager.Name); //输出刘备
manager.Say();
}

特殊问题

循环依赖

生命周期

生命周期不同阶段使用的事件

主要用于处理一些依赖关系比如在初始化该类之前某个类必须初始化好

或者当前类初始化后其他相关的类必须进行初始化 目前比较不常用

Autofac暴露五个事件接口供实例的按如下顺序调用

  1. OnRegistered
  2. OnPreparing
  3. OnActivated
  4. OnActivating
  5. OnRelease
builder.RegisterType<Worker>().As<IPerson>()
.OnRegistered(e => Console.WriteLine("在注册的时候调用!"))
.OnPreparing(e => Console.WriteLine("在准备创建的时候调用!"))
.OnActivating(e => Console.WriteLine("在创建之前调用!"))
.OnActivated(e => Console.WriteLine("创建之后调用!"))
.OnRelease(e => Console.WriteLine("在释放占用的资源之前调用!"));

默认有三种生命周期:

1.Per Dependency:默认的生命周期 每次请求都创建一个新的对象
2.Single Instance:单例模式  每次都用同一个对象
3.Per Lifetime Scope:同一个生命周期生成的对象是同一个实例

  public class 生命周期
{
/// <summary>
/// 默认生命周期
/// </summary>
[TestMethod]
public void PerDependency()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().InstancePerDependency();
IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>();
Assert.IsFalse(object.ReferenceEquals(class1, class2));
} /// <summary>
/// 单例 每次都用同一个对象(不同用户使用相同的第一次实例)
/// </summary>
[TestMethod]
public void SingleInstance()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().SingleInstance(); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>();
Assert.IsTrue(object.ReferenceEquals(class1, class2));
} /// <summary>
/// 同一生命周期内使用同一个对象
/// </summary>
[TestMethod]
public void PerLifetimeScope()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestClass>().InstancePerLifetimeScope(); IContainer container = builder.Build();
var class1 = container.Resolve<TestClass>();
var class2 = container.Resolve<TestClass>(); ILifetimeScope inner = container.BeginLifetimeScope();
var class3 = inner.Resolve<TestClass>();
var class4 = inner.Resolve<TestClass>(); Assert.IsTrue(object.ReferenceEquals(class1, class2));
Assert.IsFalse(object.ReferenceEquals(class1, class3));
Assert.IsTrue(object.ReferenceEquals(class3, class4));
} }

config配置注入

  static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<AutoFacManager>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
using (IContainer container = builder.Build())
{
AutoFacManager manager = container.Resolve<AutoFacManager>();
manager.Say();
} Console.ReadKey();
}

AutoFac在MVC中的应用

参考资料:http://docs.autofac.org/en/latest/

AutoFac记录的更多相关文章

  1. 记录对依赖注入的小小理解和autofac的简单封装

    首先,我不是一个开发者,只是业余学习者.其次我的文化水平很低,写这个主要是记录一下当前对于这块的理解,因为对于一个低水平 的业余学习者来说,忘记是很平常的事,因为接触.应用的少,现在理解,可能过段时间 ...

  2. 个人项目框架搭建 -- Autofac简单使用记录

    1.添加autofac相关程序集/使用Nuget 2.引入命名空间 using Autofac; using Autofac.Configuration; 3.使用 3.1:直接使用 var buil ...

  3. autofac 学习记录

    builder.RegisterModule(new ConfigurationSettingsReader()); 需要注册上面一句才能读到.config里的节点,xml配置方式如下 <con ...

  4. 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证

    前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介 ...

  5. 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)

    前言 在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代 ...

  6. .NET 4.5+项目迁移.NET Core的问题记录

    .NET 4.5+项目迁移.NET Core的问题记录 这几天试着把目前的开发框架迁移到新的.net core平台,中间遇到的问题在这里简单记录一下. 迁移过程遇到的最大的问题IOC容器.我目前使用的 ...

  7. Autofac Container 的简单的封装重构

    为了使用方便,对Autofac container的简单封装,记录如下,备以后用或分享给大家,欢迎讨论! using Autofac; using Autofac.Core.Lifetime; usi ...

  8. Ioc容器Autofac系列(1)-- 初窥

     一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...

  9. Ioc Autofac心得

    对于这个容器注入,个人也不是很熟悉,很多还不懂,只会基本的操作,几天把它记录下来,说不定以后帮助就大了呢,这方面跟安卓差距还是挺大的 下面记录下应用的流程 步骤: 1.添加应用 2.重写工厂(这里讲的 ...

随机推荐

  1. Gson 与 fastJson 在使用上的差异(fastJson的优点)

    一.android 常用的json解析方式 Android 开发上常用的json解析方式有:Gson, fastJson,jackson. 因为jackjson jar包会比较大点(700+k),Gs ...

  2. IntelliJ IDEA全局内容搜索和替换

      在做项目时,有时会在整个项目里或指定文件夹下进行全局搜索和替换,这是一个很方便功能.使用方法如下: 一.全局搜索 1.使用快捷键Ctrl+Shift+F打开搜索窗口,或者通过点击Edit–> ...

  3. Java -Dfile.encoding=UTF-8 干掉乱码

    遭遇乱码问题的来龙去脉 这两天写了一个 Java 程序来玩,结果又遭遇了以前遇到过很多次的乱码问题,具体描述一下:在 Mac 系统里面,常用的 Java 程序启动方式有如下几种:1.通过 eclips ...

  4. [leetcode]Unique Paths II @ Python

    原题地址:https://oj.leetcode.com/problems/unique-paths-ii/ 题意: Follow up for "Unique Paths": N ...

  5. 从源码编译InfluxDB

    操作系统 : CentOS7.3.1611_x64 go语言版本:1.8.3 linux/amd64 InfluxDB版本:1.1.0 go语言安装参考: http://www.cnblogs.com ...

  6. 网站菜单CSS

    #site-nav .down-menu a{height:88px;line-height:88px;border-bottom:0px solid #9e5ae2;transition-durat ...

  7. 12C -- DDL日志

    DDL日志和alert日志有相似的格式和行为.但是只包含DDL语句日志.oracle只是为数据库组件提供DDL日志,且需要将参数enable_ddl_logging设置为true. 在DDL日志中,每 ...

  8. php手册总结《类》

    手册页面: http://php.net/manual/zh/language.oop5.basic.php >> 类名 类名可以是任何非 PHP 保留字的合法标签.一个合法类名以字母或下 ...

  9. Atitit 数据融合merge功能v3新特性.docx

    Atitit 数据融合merge功能v3新特性.docx 1.1. 版本历史1 1.2. 生成sql结果1 1.3. 使用范例1 1.4. 核心代码1 1.1. 版本历史 V2增加了replace部分 ...

  10. 【Jetty】Jetty 的工作原理以及与 Tomcat 的比较

    Jetty 应该是目前最活跃也是很有前景的一个 Servlet 引擎.本文将介绍 Jetty 基本架构与基本的工作原理:您将了解到 Jetty 的基本体系结构:Jetty 的启动过程:Jetty 如何 ...