AutoFac记录
概念
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提供几种不同的参数对应策略:
- NamedParameter :像上面那样对应的参数名字
- TypedParameter:对应到参数的类型(必须是具体的类型)
- ResolvedParameter:灵活的参数匹配
- NamedParameter 和TypedParameter:只能提供常量参数
3、从表达式中使用参数
如果使用表达式注册的方式,可以使用第二个可用的委托参数来获得参数。
![](https://common.cnblogs.com/images/copycode.gif)
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暴露五个事件接口供实例的按如下顺序调用
- OnRegistered
- OnPreparing
- OnActivated
- OnActivating
- 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记录的更多相关文章
- 记录对依赖注入的小小理解和autofac的简单封装
首先,我不是一个开发者,只是业余学习者.其次我的文化水平很低,写这个主要是记录一下当前对于这块的理解,因为对于一个低水平 的业余学习者来说,忘记是很平常的事,因为接触.应用的少,现在理解,可能过段时间 ...
- 个人项目框架搭建 -- Autofac简单使用记录
1.添加autofac相关程序集/使用Nuget 2.引入命名空间 using Autofac; using Autofac.Configuration; 3.使用 3.1:直接使用 var buil ...
- autofac 学习记录
builder.RegisterModule(new ConfigurationSettingsReader()); 需要注册上面一句才能读到.config里的节点,xml配置方式如下 <con ...
- 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证
前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介 ...
- 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)
前言 在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代 ...
- .NET 4.5+项目迁移.NET Core的问题记录
.NET 4.5+项目迁移.NET Core的问题记录 这几天试着把目前的开发框架迁移到新的.net core平台,中间遇到的问题在这里简单记录一下. 迁移过程遇到的最大的问题IOC容器.我目前使用的 ...
- Autofac Container 的简单的封装重构
为了使用方便,对Autofac container的简单封装,记录如下,备以后用或分享给大家,欢迎讨论! using Autofac; using Autofac.Core.Lifetime; usi ...
- Ioc容器Autofac系列(1)-- 初窥
一.前言 第一次接触Autofac是因为CMS系统--Orchard,后来在一个开源爬虫系统--NCrawler中也碰到过,随着深入了解,我越发觉得Ioc容器是Web开发中必不可少的利器.那么,Io ...
- Ioc Autofac心得
对于这个容器注入,个人也不是很熟悉,很多还不懂,只会基本的操作,几天把它记录下来,说不定以后帮助就大了呢,这方面跟安卓差距还是挺大的 下面记录下应用的流程 步骤: 1.添加应用 2.重写工厂(这里讲的 ...
随机推荐
- Asp.Net JsonResult重写
在Json序列化工具中,Newtonsoft.Json 的工具包相对比较好用. 对于循环引用.序列化格式.时间格式等都提供了可配置. 如果想重写Mvc 自带 JsonResult 返回结果,提供了2中 ...
- 6、Python变量
Python变量 变量的定义 变量是计算机内存中的一块区域,变量可以存储规定范围内的值,而且值可以改变. 变量的命名 变量名有字母.数字.下划线组成. 数字不能开头 不可以使用关键字 a a1 a_ ...
- 全景分割pipeline搭建
全景分割pipeline搭建 整体方法使用语义分割和实例分割结果,融合标签得到全景分割结果: 数据集使用:panoptic_annotations_trainval2017和cityscapes; p ...
- js,html-点击直接跳转到页面底/顶部
案例一:js控制,无滑动效果 <html> <body> <a href="javascript:void(0);" onclick="ja ...
- Kafka:ZK+Kafka+Spark Streaming集群环境搭建(三十):使用flatMapGroupsWithState替换agg
flatMapGroupsWithState的出现解决了什么问题: flatMapGroupsWithState的出现在spark structured streaming原因(从spark.2.2. ...
- vue中使用some删除list中的数据
在vue中可以使用some方法查找需要删除的所以 this.list.some((item, i) => { if (item.id == id) { this.list.splice(i, 1 ...
- MFC总结之CListCtrl用法及技巧
复制于:http://www.cnblogs.com/lidabo/archive/2012/08/23/2652796.html 1.基本操作 分别从下面四点来介绍CListCtrl的基本操作: ① ...
- Mybatis3.3——源码阅读笔记
目录 Mybatis--Source阅读笔记 兵马未动,日志先行 异常 缓存 回收机制适配器 回收机制优化缓存 事务缓存 调试型缓存--日志缓存 解析 类型处理器 IO VFS Resource Re ...
- Nginx实现url请求不区分大小写
原文地址:http://blog.linuxeye.com/382.html 如果你将跑在Windows下的项目(如:php)迁移到Linux下,由于Windows操作系统中,文件名是不区分大小写的: ...
- Linux内核修炼之framebuffer分析
Linux源代码包中/document/fb/framebuffer.txt有例如以下介绍: The frame buffer device provides an abstraction for t ...