概念

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. JVM Debugger Memory View for IntelliJ IDEA

    Posted on August 19, 2016 by Andrey Cheptsov Every day we try to find new ways to improve developer ...

  2. anaconda3/lib/libcrypto.so.1.0.0: no version information available (required by wget)

    Solution: sudo ldconfig /lib/x86_64-linux-gnu/ #you need to use the libcrypto.so from /lib/x86_64-li ...

  3. Juno Puppet Opertaors Meetup小结

    今年五月刚结束的Juno OpenStack Summit是半年一度的Openstack盛会,抛去那些迷花渐欲乱人眼的商业活动,我们来看一看本届summit puppet-openstack社区有哪些 ...

  4. MFC总结之CListCtrl用法及技巧

    复制于:http://www.cnblogs.com/lidabo/archive/2012/08/23/2652796.html 1.基本操作 分别从下面四点来介绍CListCtrl的基本操作: ① ...

  5. 【Linux】linux/unix下telnet提示Escape character is '^]'的意义

    在linux/unix下使用telnet hostname port连接上主机后会提示Escape character is '^]' 这个提示的意思是按Ctrl + ] 会呼出telnet的命令行, ...

  6. ios开发版证书与企业证书相关文件申请安装及其使用方法

    本文主要讲述以下内容: ios开发版证书的申请, 企业证书的申请, appid的创建, provision profile的生成, 开发设备devices的绑定, 以及每个证书文件之间的关系, 最后使 ...

  7. Nginx-rtmp 直播媒体实时流实现

    0. 前言 这段时间在搭建一个IPCamera项目服务器.视频点对点通话,客户端会查看设备端的音视频实时流.为了省流量,是通过P2P进行穿透.但是由于NAT设备的原因和IPV4的枯竭.有些设备是无法进 ...

  8. 【Android】Android布局文件的一些属性值

    第一类:属性值 true或者 false   android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 androi ...

  9. 【Ubuntu】xrdp完美实现Windows远程访问Ubuntu 16.04

    步骤一.下载TigerVNC Server软件包 下载地址:Tigervnc Deb软件包(适用于Ubuntu 16.04.1 - 64位) 步骤二. 安装TigerVNC Server软件包 1.打 ...

  10. java Filter过滤器例外URL设置

    在web.xml声明的一个filter中: <!– session过滤filter –> <filter> <filter-name>SessionFilter&l ...